Not every group of values needs to be a list. The cinema wants a seat coordinate, a unique list of visiting customer IDs, and a record of every purchase. Those are three different needs.
You need: lists and dictionaries. By the end: you can explain when to choose a tuple or set and what information a conversion might discard. Allow 25–35 minutes.
Tuples: a fixed group of values
seat = ("C", 7)
row, number = seat
print(row)
print(number)
print(seat[0])
Output:
C
7
C
A tuple is an ordered, immutable sequence. You can retrieve positions, but cannot assign a different value to seat[0]. Unpacking assigns its two values to two names; the number of names must match the number of values in this simple form.
Tuples are useful for small fixed groups whose positions are obvious. A record with many fields is often clearer as a dictionary. ("C",) is a one-item tuple; the comma matters. ("C") is just a string in parentheses.
Immutable does not mean that everything inside is recursively frozen. A tuple can hold a mutable list. We will revisit that distinction when studying shared references.
Sets: uniqueness without positions
visitor_ids = ["C01", "C02", "C01", "C03"]
unique_visitors = set(visitor_ids)
print(len(visitor_ids))
print(len(unique_visitors))
print("C02" in unique_visitors)
Output:
4
3
True
A set holds unique elements and supports membership checks. It has no positional indexing and does not guarantee a useful iteration order. Do not write a test that expects a printed set’s elements to appear in a particular order.
Use set() for an empty set: {} creates an empty dictionary. Like dictionary keys, set elements must be hashable; our strings qualify, but lists and dictionaries do not.
checked_in = set()
checked_in.add("B001")
checked_in.add("B001")
checked_in.add("B002")
checked_in.discard("B002")
print(len(checked_in))
This prints 1. Adding the same value twice has no extra effect. discard() removes a value if present and does nothing if absent. remove() would raise KeyError when the value is absent; choose according to whether absence is expected.
Compare groups directly
booked = {"B001", "B002", "B003"}
checked_in = {"B001", "B003", "B999"}
missing = booked - checked_in
unexpected = checked_in - booked
matched = booked & checked_in
print(sorted(missing))
print(sorted(unexpected))
print(sorted(matched))
Output:
['B002']
['B999']
['B001', 'B003']
- computes a difference; & computes an intersection; | computes a union. These operations create new sets. sorted() produces a sorted list for stable display; it does not change the sets.
This is a small reconciliation task: who booked but did not arrive, and who arrived without a matching booking?
Performance is a tradeoff, not a slogan
Membership in a set is usually roughly constant time on average, whereas a list search may inspect every item. If checking many IDs against the same group, create the set once, outside the loop. Rebuilding it for every check throws away much of the benefit.
Sets also require memory and discard duplicate counts and sequence information. Converting purchase records to a set can destroy the very information needed for revenue totals. “Faster” is not useful if the answer changes.
| Need | Starting choice |
|---|---|
| Keep every booking in order | List |
| Store a record with named fields | Dictionary |
| Represent a fixed pair such as row and seat | Tuple |
| Check unique IDs or compare groups | Set |
These are starting choices, not universal laws. A small list may already be fast enough. Avoid creating multiple representations without a clear use for each.
Your turn: two screenings
Morning visitors are ['C01', 'C02', 'C01']; evening visitors are ['C02', 'C03']. Find the total number of unique visitors and the IDs of people who attended both screenings.
Show one solution
morning = set(["C01", "C02", "C01"])
evening = set(["C02", "C03"])
all_visitors = morning | evening
repeat_visitors = morning & evening
print(len(all_visitors))
print(sorted(repeat_visitors))
The answers are 3 and ['C02']. The repeated C01 entry no longer contributes an extra occurrence. Keep the original data too if occurrence counts matter.
Checkpoint: explain why a set helps with repeated membership checks but is a poor replacement for an ordered purchase history.