Skip to main content

Someone wanted to learn this too, so Grasp built them a personal learning path.

You can keep exploring this one or create your own

Working with Tuples, Sets, and Dictionaries

Hello! Last time, you used strings and lists to hold values in order, retrieve them by position, and change list items. But position is not always the right way to find something. If you have a task record, you would rather ask for its "status" than remember that status happens to be item 2.

In this lesson, you’ll use tuples for fixed sequences, sets for unique items, and dictionaries for values retrieved by a key. You’ll create each collection, retrieve information from it, and learn what can be updated. Allow about 40–45 minutes, including the video, reading, and time to run the examples in Colab.


Tuples: a sequence you cannot change in place

A tuple resembles a list: it has an order, supports indexing and slicing, and can hold different types of values. The difference is that a tuple’s items cannot be replaced, added, or removed after creation. That makes it a useful choice when the positions themselves have a fixed meaning, such as a pair containing an hour and a minute.

meeting_time = (14, 30)

print(meeting_time[0])   # 14: hour
print(meeting_time[-1])  # 30: minute
print(meeting_time[:1])  # (14,)

hour, minute = meeting_time
print(f"Meeting at {hour}:{minute:02d}")  # Meeting at 14:30

The assignment hour, minute = meeting_time is called unpacking. Python assigns the tuple’s first item to hour and its second to minute; the number of names must match the number of items.

Watch the tuple portion of Python: Data Structures - Lists, Tuples, Sets & Dictionaries tutorial by Programming and Math Tutorials. It shows both tuple construction and what immutability does—and does not—prevent.

Python: Data Structures - Lists, Tuples, Sets & Dictionaries tutorial

Watch the tuple segment to connect familiar sequence indexing with the new restriction on updates.

Watch tuples. Pay particular attention to the trailing comma in a one-item tuple and to the example with a list inside a tuple. You can skip the presenter’s performance comparison; choosing between a tuple and a list here is about what the data represents.

The comma, rather than the parentheses alone, makes a one-item tuple:

not_a_tuple = ("draft")
one_item_tuple = ("draft",)

print(type(not_a_tuple))    # <class 'str'>
print(type(one_item_tuple)) # <class 'tuple'>

Trying meeting_time[0] = 15 would raise a TypeError. If the meeting time changes, create a new tuple and assign it to the name:

meeting_time = (14, 30)
meeting_time = (15, 30)

print(meeting_time)  # (15, 30)

The name now refers to a different tuple; the original tuple was not modified. There is one subtlety: a tuple can contain a mutable object, such as a list. You cannot replace that list’s position in the tuple, but you can still change the list itself. For a genuinely fixed record, prefer items that are themselves immutable.


Sets: keep distinct values, not positions

Suppose a task-automation program collects action labels from several requests. It may need to know which different actions appear, regardless of how often each was requested. A set answers that question: it contains no duplicates and has no positional indexing.

requested = ["draft", "review", "draft", "schedule"]
unique_actions = set(requested)

print(len(requested))       # 4
print(len(unique_actions))  # 3
print("review" in unique_actions)  # True

The printed order of unique_actions is not guaranteed. You cannot retrieve unique_actions[0]; there is no “first action” in a set. Keep the list if request order or repeated requests matter. Also notice that set(requested) creates a new collection; it does not change requested.

A nonempty set can be written with braces, while an empty set must be made with set(). Empty braces, {}, create a dictionary instead.

permitted_actions = {"draft", "review"}
permitted_actions.add("schedule")
permitted_actions.add("draft")  # No duplicate is added

permitted_actions.discard("review")
print("review" in permitted_actions)  # False

nothing_yet = set()
print(type(nothing_yet))  # <class 'set'>

discard() is convenient when an item might be absent: it does nothing in that case. remove() also deletes an item, but raises a KeyError if the item is not there. Set elements must be suitable for membership-based storage: strings and numbers work, as do tuples whose contents are suitable; lists cannot be set elements.

Watch the set segment of the same tutorial for a visual walkthrough of construction, updates, membership, and comparisons.

Python: Data Structures - Lists, Tuples, Sets & Dictionaries tutorial

Continue with the set segment to see why uniqueness and membership are more useful here than indexing.

Watch sets. Focus on converting a list to a set, adding and removing items, and the intersection, union, and difference operators. When the presenter discusses pop(), remember that it removes an arbitrary set element: do not use it when you need a particular one.

Sets can also compare collections of distinct values. In the following example, the intersection contains actions in both sets; the difference contains actions requested but not permitted.

requested_actions = {"draft", "send", "schedule"}
permitted_actions = {"draft", "review", "schedule"}

print(requested_actions & permitted_actions)  # {'draft', 'schedule'}
print(requested_actions - permitted_actions)  # {'send'}
print(requested_actions | permitted_actions)  # All four distinct actions

The order shown when any of these sets is printed may differ in your notebook. The membership of each result—not its printed order—is what matters.


Dictionaries: retrieve a value by its label

A tuple lets you ask for meeting_time[0] because position 0 means “hour.” A dictionary lets you give the position a meaningful label instead. It stores key–value pairs: a key identifies the value you want.

An illustration of dictionary key–value pairs and the operations of accessing, adding, and deleting entries. In Python code, the key goes inside square brackets when you retrieve or update its value.

Read “5.5. Dictionaries” in the official Python documentation’s 5. Data Structures. It establishes the rules for keys, assignment, and missing-key lookups that you will use in the next examples.

5. Data Structures — Python 3.14.0 documentation

Read the “5.5. Dictionaries” subsection to see how storing by key differs from selecting a sequence item by position.

In “5.5. Dictionaries,” begin with the paragraph starting “Another useful data type built into Python is the dictionary.” Read keys and pairs, focusing on why a list cannot be a key. Continue from “The main operations on a dictionary are storing a value with some key” through lookup rules. Stop just before the telephone-number example, and compare d[key] with get() when a key is missing.

Here is a task record. The braces contain pairs separated by commas; within each pair, a colon separates the key from its value. The keys below are strings, but the values have different types.

task = {
    "action": "draft",
    "priority": 2,
    "confirmed": False,
    "time": (14, 30),
}

print(task["action"])    # draft
print(task["time"][0])   # 14: retrieve the tuple, then its hour
print(len(task))         # 4 key-value pairs

Dictionary keys must be hashable—for this stage, think of strings, numbers, and tuples made of hashable items as suitable choices. A list cannot be a key because its contents can change. Values have no such restriction: a dictionary value can be a list, tuple, set, or another dictionary.

A dictionary is mutable. Assignment to a new key adds a pair; assignment to an existing key replaces its value. Keys remain unique.

task = {"action": "draft", "priority": 2}

task["status"] = "pending"   # Add a pair
task["priority"] = 1         # Replace the value for an existing key

print(task)  # {'action': 'draft', 'priority': 1, 'status': 'pending'}

del task["status"]           # Delete the pair with this key
print(task)  # {'action': 'draft', 'priority': 1}

Unlike a set, a dictionary preserves insertion order when you iterate over or print its entries. But you still retrieve a value using its key, not a numeric position: task["action"], not task[0].

A missing key is a common source of errors. task["deadline"] raises a KeyError if there is no "deadline" key. Use .get() when absence is expected:

task = {"action": "draft", "priority": 2}

print(task.get("deadline"))              # None
print(task.get("deadline", "not set"))   # not set
print("deadline" in task)                # False
print("action" in task)                  # True

For a dictionary, in checks keys, not values: "draft" in task is False here. The distinction between task["action"] and task.get("action") is intentional: use square brackets when the key must exist, and .get() when missing data is normal.


Choose the collection that matches the question

These types can work together without becoming interchangeable. Imagine representing one requested action, checking whether its label is permitted, and then recording a status:

permitted_actions = {"draft", "review", "schedule"}
requested_action = "draft"
requested_time = (14, 30)

task = {
    "action": requested_action,
    "time": requested_time,
    "status": "pending",
}

print(task["action"] in permitted_actions)  # True
print(task.get("owner", "unassigned"))      # unassigned

task["status"] = "ready"
print(task["status"])  # ready

Each collection has a distinct job. The set answers whether an action label is permitted. The tuple keeps the hour and minute together in fixed positions. The dictionary lets you retrieve and change the task’s status by its name. If you needed to preserve multiple requests in arrival order, a list would still be the appropriate outer collection.

You can make that choice by asking what retrieval means for the data:

Collection Retrieve by Can its contents be updated? Good fit
Tuple Position No item replacement A fixed group such as (hour, minute)
Set Membership Yes: add or remove distinct items Permitted action labels
Dictionary Key Yes: add, replace, or delete pairs A task record with labeled fields

Takeaway

Tuples retain sequence order but do not allow item replacement. Sets discard duplicates and support membership and set comparisons, but not indexing. Dictionaries map unique keys to values: square brackets retrieve or assign by key, while .get() handles an expected missing key. Choosing among them depends less on what the values are than on how your program needs to find and change them.

Next, you’ll use conditionals and loops to make decisions from these collections and process more than one item automatically.

Can't find a good explanation? Sign up and we'll make it for you

Sign up