reference
5 min read
·
lesson 6 of 16 in Reference
Python Tuple Cheat Sheet
1 · The lesson
readImmutable ordered sequence. Like a list, but you cannot change it after creation. Hashable (if its items are), so usable as dict keys and set members. For the full tutorial, see Tuples.
Creating
python
a = (1, 2, 3) b = 1, 2, 3 # parens optional — still a tuple c = () # empty d = (42,) # SINGLE element — comma required e = (42) # NOT a tuple — just int 42 f = tuple([1, 2, 3]) # from iterable g = tuple("abc") # ('a', 'b', 'c') h = tuple(range(3)) # (0, 1, 2)
The comma — not the parens — makes the tuple. (42,) is a one-tuple; (42) is an int.
Indexing & Slicing
Same syntax as lists, but read-only:
python
t = (10, 20, 30, 40, 50) t[0] # 10 t[-1] # 50 t[1:4] # (20, 30, 40) t[::-1] # (50, 40, 30, 20, 10) len(t) # 5 30 in t # True t.count(20) # 1 t.index(30) # 2 t[0] = 99 # TypeError — immutable
Only two methods: .count() and .index().
Why Use Tuples
| Reason | Detail |
|---|---|
| Hashable | Can be a dict key or set element (if items hashable too) |
| Immutable contract | Signals "don't change this" — safer to pass around |
| Function returns | Multiple return values are tuples: return a, b |
| Faster | Slightly faster than lists, smaller memory footprint |
| Fixed schema | Coordinates, RGB, (x, y, z) — known shape |
python
# dict key locations = {(40.7, -74.0): "NYC", (51.5, -0.1): "London"} # set element seen = {(1, 2), (3, 4)} # Lists can't do either — unhashable {[1, 2]} # TypeError
Unpacking
python
t = (1, 2, 3) a, b, c = t # 1, 2, 3 a, b = 1, 2 # without parens — same thing # Starred (3.0+) first, *rest = (1, 2, 3, 4) # first=1, rest=[2, 3, 4] *init, last = (1, 2, 3, 4) # init=[1, 2, 3], last=4 a, *mid, z = (1, 2, 3, 4, 5) # a=1, mid=[2,3,4], z=5 # Ignore with _ name, _, age = ("Ada", "ignored", 36) for _, value in items: # ignore key ... # Nested ((a, b), c) = ((1, 2), 3) # a=1, b=2, c=3
setup added so this can run · defines items
items = [("alpha", 1), ("beta", 2), ("gamma", 3)]
namedtuple (collections)
python
from collections import namedtuple Point = namedtuple("Point", ["x", "y"]) p = Point(1, 2) p.x # 1 p[0] # 1 — still indexable p._asdict() # {'x': 1, 'y': 2} p._replace(x=99) # Point(x=99, y=2) — new instance
typing.NamedTuple
Modern, typed, class-syntax version:
python
from typing import NamedTuple class Point(NamedTuple): x: int y: int = 0 # default value def magnitude(self) -> float: return (self.x ** 2 + self.y ** 2) ** 0.5 p = Point(3, 4) p.magnitude() # 5.0
See Type Hints and Collections Cheat Sheet.
Common Patterns
python
# Swap variables a, b = b, a # Multiple return values def divmod_(a, b): return a // b, a % b q, r = divmod_(17, 5) # Coordinate pairs point = (3, 4) x, y = point # As dict keys for compound lookups cache = {} cache[(user_id, date)] = result # Tuple of args (splat in) args = (1, 2, 3) sum_three(*args) # sum_three(1, 2, 3) # Convert list -> tuple (e.g. to use as dict key) key = tuple(sorted(items)) # Enumerate yields tuples for i, x in enumerate(xs): ... # zip yields tuples for a, b in zip(xs, ys): ...
setup added so this can run · defines result, sum_three, xs, ys, user_id, date, items
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) result = _AutoMock('result') def sum_three(*_a, **_kw): print('-> sum_three() called') return _AutoMock('sum_three()') xs = _AutoMock('xs') ys = _AutoMock('ys') user_id = _AutoMock('user_id') date = _AutoMock('date') items = _AutoMock('items')
Tuple vs List
| Property | Tuple | List |
|---|---|---|
| Mutable | No | Yes |
| Hashable | Yes (if items are) | No |
| Syntax | (1, 2) | [1, 2] |
| Methods | 2 (count, index) | ~11 |
| Use case | Fixed records, keys | Growing collections |
| Performance | Slightly faster | Slightly slower |
Common Errors
| Error | Cause | Fix |
|---|---|---|
TypeError: 'tuple' object does not support item assignment | t[0] = x | Tuples are immutable. Build a new tuple: (x,) + t[1:], or use a list |
TypeError: 'tuple' object has no attribute 'append' | Treating tuple as list | Use a list, or t = t + (x,) to make a new tuple |
ValueError: too many values to unpack (expected 2) | a, b = (1, 2, 3) | Match counts: a, b, c = ... or use a, b, *_ = ... |
ValueError: not enough values to unpack (expected 3, got 2) | a, b, c = (1, 2) | Right-hand side must have enough items |
(42) not a tuple | Missing trailing comma | (42,) for a one-tuple |
TypeError: unhashable type: 'list' when using tuple as key | Tuple contains a list | All items must be hashable; convert inner list to tuple |