Python Tuple Cheat Sheet
1 · The lesson
readA tuple is an ordered group of values, like a list, but you cannot change it after you create it. Use a tuple for a small, fixed record, such as a point (3, 4) or a name and an age. Because a tuple cannot change, it can be a dictionary key or a set member. A list cannot be either. For the full tutorial, see Tuples.
1. Create a tuple
The comma makes the tuple, not the brackets. A tuple with one item needs a comma after the item.
1, 2 # (1, 2) (42,) # (42,) (one item: the comma is required) (42) # 42 (no comma, so this is just the number 42) () # () (an empty tuple) tuple("abc") # ('a', 'b', 'c') (anything you can loop over becomes a tuple) tuple([1, 2]) # (1, 2) (a list turned into a tuple) tuple(range(3)) # (0, 1, 2)
2. Read items
Indexing and slicing work exactly as they do for lists. A tuple has only two methods: count() and index().
t = (10, 20, 30, 40) t[0] # 10 (the first item) t[-1] # 40 (the last item) t[1:3] # (20, 30) (a slice of a tuple is a tuple too) t[::-1] # (40, 30, 20, 10) len(t) # 4 30 in t # True t.count(20) # 1 t.index(30) # 2 min(t), max(t), sum(t) # (10, 40, 100)
3. Build a new tuple
You cannot change a tuple, but you can build a new one from parts of the old one. If you need to make many changes, turn it into a list first.
(1, 2) + (3,) # (1, 2, 3) (+ joins two tuples into a new tuple) (0,) * 3 # (0, 0, 0) t[:1] + (99,) + t[2:] # (10, 99, 30, 40) (a new tuple with the second item replaced) list(t) # [10, 20, 30, 40] sorted((3, 1, 2)) # [1, 2, 3] (sorted() always returns a list) tuple(sorted((3, 1, 2))) # (1, 2, 3)
setup added so this can run · re-runs 1 earlier block on this page first
t = ["alpha", "beta", "gamma"] # Earlier blocks on this page that this one builds on, re-run quietly first. _pm_earlier = [ 't = (10, 20, 30, 40)\nt[0] # 10 (the first item)\nt[-1] # 40 (the last item)\nt[1:3] # (20, 30) (a slice of a tuple is a tuple too)\nt[::-1] # (40, 30, 20, 10)\nlen(t) # 4\n30 in t # True\nt.count(20) # 1\nt.index(30) # 2\nmin(t), max(t), sum(t) # (10, 40, 100)', ] def _pm_run_earlier(_srcs, _g): import sys as _s, io as _io, warnings as _w for _src in _srcs: _o, _e = _s.stdout, _s.stderr _s.stdout = _s.stderr = _io.StringIO() try: with _w.catch_warnings(): _w.simplefilter('ignore') exec(compile(_src, '<earlier block>', 'exec'), _g) except (Exception, SystemExit): pass finally: _s.stdout, _s.stderr = _o, _e if 'matplotlib.pyplot' in _s.modules: _s.modules['matplotlib.pyplot'].close('all') # their plots belong to their own blocks _pm_run_earlier(_pm_earlier, globals()) del _pm_earlier, _pm_run_earlier
4. Compare tuples
Python compares tuples item by item, from left to right. The first pair of items that differ decides the result. This is why sorting a list of tuples sorts by the first item, then by the second item when the first items are equal.
(1, 2) == (1, 2) # True (1, 9) < (2, 0) # True (1 is smaller than 2, so the rest does not matter) (1, 2) < (1, 2, 0) # True (a shorter tuple that matches the start comes first) max([("b", 2), ("a", 9)]) # ('b', 2)
5. Unpack a tuple
Unpacking puts each item of a tuple into its own variable, in one line. A name with * collects all the remaining items into a list. Use _ as the name for an item you do not need.
x, y = (3, 4) y # 4 first, *rest = (1, 2, 3, 4) rest # [2, 3, 4] *init, last = (1, 2, 3, 4) init # [1, 2, 3] name, _, age = ("Ada", "London", 36) age # 36 (a, b), c = (1, 2), 3 # a tuple inside a tuple unpacks the same way b # 2 a, b = 1, 2 a, b = b, a # swap two values without a temporary variable a # 2
enumerate() gives (index, item) tuples, and the for loop unpacks each tuple:
for i, ch in enumerate("ab"): print(i, ch)
0 a 1 b
6. Tuples and functions
When a function returns several values separated by commas, it returns one tuple. A * in front of a parameter name collects any extra arguments into a tuple.
def min_max(xs): return min(xs), max(xs) lo, hi = min_max([3, 1, 2]) hi # 3 divmod(17, 5) # (3, 2) (built-in functions return tuples too) list(zip("ab", (1, 2))) # [('a', 1), ('b', 2)] list({"a": 1}.items()) # [('a', 1)] (dictionary items are (key, value) tuples) pow(*(2, 10)) # 1024 (* passes each item as a separate argument) def total(*nums): # nums is a tuple of all the arguments return sum(nums) total(1, 2, 3) # 6
setup added so this can run · defines nums
# 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,) nums = _AutoMock('nums')
7. Tuples as dictionary keys and set members
A value can be a dictionary key or a set member only if it is hashable: Python can compute a fixed number from it, which needs a value that never changes. A tuple is hashable when every item inside it is hashable. A list is never hashable.
dist = {("Paris", "Rome"): 1106}
dist[("Paris", "Rome")] # 1106
len({(0, 0), (0, 0), (1, 2)}) # 2 (a set of grid points; the duplicate is dropped)
tuple(sorted(["b", "a"])) # ('a', 'b') (turn a list into a tuple to use it as a key){[1, 2]: "x"} raises TypeError: unhashable type: 'list' (full error page).
8. namedtuple
A namedtuple is a tuple whose items also have names, so p.x is easier to read than p[0].
from collections import namedtuple Point = namedtuple("Point", ["x", "y"]) p = Point(3, 4) p # Point(x=3, y=4) p.x # 3 (reads an item by its name) p[1] # 4 (or by its index) p._replace(x=0) # Point(x=0, y=4) (a new tuple with a new x) p._asdict() # {'x': 3, 'y': 4} p == (3, 4) # True (it is still a normal tuple) Point._fields # ('x', 'y')
9. typing.NamedTuple
typing.NamedTuple does the same job, but you write it as a class. A class lets you add types, default values and methods.
from typing import NamedTuple class Point(NamedTuple): x: int y: int = 0 # a default value def length(self) -> float: return (self.x ** 2 + self.y ** 2) ** 0.5 Point(5) # Point(x=5, y=0) Point(3, 4).length() # 5.0
See Type hints and Collections.
10. Tuple or list?
| Tuple | List | |
|---|---|---|
| Can it change? | No | Yes |
| Can it be a dict key? | Yes, if its items are hashable | No |
| Written as | (1, 2) | [1, 2] |
| Methods | 2 (count, index) | 11 |
| Good for | A fixed record where each position means something: (x, y) | A collection of the same kind of thing that grows: scores |
Common mistakes
Forgetting the comma in a one-item tuple. ("a") is just the string 'a'. Write ("a",).
A stray comma. A comma at the end of a line makes a tuple, even without brackets:
x = 1, x # (1,)
Changing an item. t[0] = 99 raises TypeError: 'tuple' object does not support item assignment. Build a new tuple, or use a list.
Calling list methods. t.append(50) raises AttributeError: 'tuple' object has no attribute 'append'. Write t = t + (50,).
Unpacking the wrong number of items. a, b = (1, 2, 3) raises ValueError: too many values to unpack (full error page). Use a, b, *_ = (1, 2, 3) to ignore the extra items.
Expecting a list inside a tuple to stay fixed. The tuple cannot change which objects it holds, but a list inside it can still change:
u = ([1], 2) u[0].append(9) u # ([1, 9], 2)
Passing a string to tuple(). tuple("hi") splits the string into characters:
tuple("hi") # ('h', 'i') ("hi",) # ('hi',)
Comparing a tuple with a list. (1, 2) == [1, 2] is False. A tuple is never equal to a list, even with the same items.
See also
Found this useful? Share it with a friend who’s learning Python.