Data Structures and Iteration
Use Python collections and iteration patterns to write expressive, efficient, and readable data-oriented code.
Content
Tuples and Immutability
Versions:
Watch & Learn
AI-discovered learning video
Sign in to watch the learning video for this topic.
Tuples and Immutability — Why you should care (and stop mutating everything)
Quick hook: Ever wanted a list that behaves like a promise — "I won't change, trust me"? That's a tuple. It's the chill, reliable sibling of the hyperactive list.
You're coming into this after learning about lists and list comprehensions, the REPL, and PEP 8. Great — you know how to build flexible collections and write readable Python. Now we're adding stability to the toolbox: tuples and immutability. This is the natural next step when you want predictable, hashable, and sometimes faster containers.
What is a tuple, and why does immutability matter?
- Tuple: an ordered collection of items, like a list, but immutable — you can't change it after creation.
- Immutability: the property of an object you can't alter in-place. If you need a different value, you create a new object.
Why it matters for data work and development:
- Safety: fixed records (like rows of metadata) shouldn't be accidentally mutated.
- Hashability: tuples (containing only hashable items) can be used as keys in dictionaries or members of sets — lists cannot.
- Performance: for small, fixed collections, tuples can be slightly faster and use less memory.
- API design: functions returning multiple values often return tuples. It's a convenient, idiomatic pattern.
Creating tuples — syntax and gotchas
Basic creation
t = (1, 2, 3)
empty = ()
Parentheses are common but optional for simple cases:
t2 = 4, 5, 6 # still a tuple
The single-element trap
This one gets many newcomers:
not_a_tuple = (42) # int, not tuple
single = (42,) # tuple with one item — note the comma
also_single = 42, # trailing comma works without parentheses
Micro explanation: the comma makes the tuple. Parentheses group expressions; the comma defines the tuple.
Accessing and iterating
Tuples support indexing, slicing, and iteration just like lists:
t = ('a', 'b', 'c')
print(t[1]) # 'b'
for x in t:
print(x)
If you learned list comprehensions, remember: there is no tuple comprehension syntax. What looks like a tuple comprehension is actually a generator expression. To make a tuple from an expression, use tuple(...):
# generator expression, not a tuple literal
gen = (x*x for x in range(3))
tuple_from_gen = tuple(x*x for x in range(3))
Packing, unpacking, and extended unpacking — the good parts
Tuples make multiple-value assignment concise:
point = (10, 20)
x, y = point # unpacking
# swap variables without a temp
x, y = y, x
Extended unpacking:
a, *rest, z = [1, 2, 3, 4]
# a=1, rest=[2,3], z=4
This is extremely handy when parsing fixed-format data or splitting records.
Immutability isn't absolute — nested mutables can change
Tuples are immutable at the top level — you can't reassign items. But if a tuple holds a mutable object, that inner object can still change:
t = ([1, 2], 3)
# t[0] is a list — you can mutate it
t[0].append(4) # t is now ([1, 2, 4], 3)
# But you cannot reassign t[0] = [9]
Micro explanation: immutability applies to the container, not to the objects it references.
Hashability and use as dict keys
A big practical difference: tuples can be used as dictionary keys if they contain only hashable items.
d = {}
coords = (10, 20)
d[coords] = 'point A'
This is why tuples are often used to represent fixed coordinates, composite keys, or small records where you need set/dict membership.
Methods and operations
Tuples have few methods (because they are immutable):
- count(value)
- index(value)
Everything else is fulfilled by built-in operators: concatenation (+), repetition (*), membership (in), iteration.
Conversion is easy:
lst = [1, 2, 3]
converted = tuple(lst)
back_to_list = list(converted)
When to prefer tuples over lists (practical checklist)
- Use a tuple when the collection is a fixed record: coordinates, RGB color, immutable options.
- Use a tuple when you need to use the items as dict keys or set members.
- Use tuples for multiple return values from functions.
- Use a list when you expect to modify (append, pop, sort) the sequence frequently.
Tip: if you need named fields, consider collections.namedtuple or dataclasses.dataclass (frozen=True) for readability and explicitness.
REPL & help habits (build on what you learned earlier)
You already know the REPL and help() from the earlier module. Use these tools to explore tuples interactively:
- In REPL: dir(tuple), help(tuple)
- Inspect object types: type((1,))
- Quick sanity checks: hash((1,2)), isinstance(x, tuple)
These tiny checks save hours of debugging.
"If you're ever unsure whether something is a tuple, ask the REPL. It never lies."
PEP 8 and style notes
- PEP 8 prefers readability: if a tuple literal is long or part of a complex expression, use parentheses and line breaks.
- Use trailing commas for single-element tuples where readability or diffs matter.
- Prefer named tuples or dataclasses for structured records rather than bare tuples with magic index positions.
Example PEP 8-friendly style:
coords = (
123.456,
78.90,
)
Quick examples you will use in data work
- Returning a pair from a function:
def min_max(values):
return (min(values), max(values))
lo, hi = min_max([3, 7, 2])
- Using tuple keys for multi-index dicts:
counts = {}
for row in rows:
key = (row['country'], row['year'])
counts[key] = counts.get(key, 0) + 1
- Immutable configuration default:
DEFAULT_BOUNDS = (0, 100)
Key takeaways
- Tuples are ordered and immutable; lists are ordered and mutable.
- Use tuples for fixed records, hashable composite keys, small performance gains, and clear multi-value returns.
- Remember the single-element tuple comma — it matters.
- Immutability applies to the container, not to mutable objects inside it.
- Use the REPL and help() to inspect behavior; follow PEP 8 for readable tuple formatting.
Final memorable insight:
Think of tuples as promises: "I promise not to change this structure." If you need to break that promise, create a new tuple — Python expects you to be explicit.
Happy tuple-izing. Your future self (and your colleagues) will thank you.
Comments (0)
Please sign in to leave a comment.
No comments yet. Be the first to comment!