Chapters
Python114 chapters

CollectionsChapter 35 of 114

Tuples

An ordered sequence that cannot change, and why that is useful.

Round brackets, or none at all

Python
point = (4, 9)
also_a_tuple = 4, 9
print(point, type(point))
print(also_a_tuple)

Output

(4, 9) <class 'tuple'>
(4, 9)

It is the commas that make a tuple. The brackets only group, which is why returning several values from a function gives you a tuple without any brackets in sight.

The one-item trap

Python
one = (5,)
not_a_tuple = (5)
print(type(one), type(not_a_tuple))

Output

<class 'tuple'> <class 'int'>

An empty tuple is the exception — () works, because there is nothing to be ambiguous about.

It cannot change

Python
point = (4, 9)
try:
    point[0] = 1
except TypeError as problem:
    print("TypeError:", problem)

Output

TypeError: 'tuple' object does not support item assignment

Everything that reads a tuple works exactly as it does for a list: indexing, slicing, len(), in, looping, unpacking.

Python
point = (4, 9, 16)
print(point[0], point[-1], point[1:])
print(len(point), 9 in point)

Output

4 16 (9, 16)
3 True

Only two methods exist, because the rest would change it:

Python
values = (1, 2, 2, 3)
print(values.count(2), values.index(3))

Output

2 3

Immutable is not the same as unchangeable inside

A tuple fixes which objects it holds. If one of those objects is a list, that list can still change:

Python
row = ("Ada", [1, 2])
row[1].append(3)
print(row)

Output

('Ada', [1, 2, 3])

Why bother

  • It says the shape is fixed. A coordinate has two numbers, always.
  • It can be a dictionary key, which a list cannot, because it hashes.
  • It is slightly smaller and faster, which occasionally matters.
Python
locations = {(0, 0): "origin", (1, 2): "somewhere"}
print(locations[(0, 0)])

try:
    {[0, 0]: "nope"}
except TypeError:
    print("a list cannot be a key")

Output

origin
a list cannot be a key

Unpacking

Tuples make multiple return values read well:

Python
def min_max(numbers):
    return min(numbers), max(numbers)

low, high = min_max([3, 1, 4])
print(low, high)

Output

1 4

Named tuples, when positions get confusing

Python
from collections import namedtuple

Point = namedtuple("Point", ["x", "y"])
p = Point(4, 9)
print(p.x, p.y)
print(p[0], tuple(p))

Output

4 9
4 (4, 9)

It is still a tuple in every way, with names attached. For anything richer, a dataclass is usually the better tool.

Test yourself

3 questions

What is type((5))?

Show the answer

int — It is five in brackets. A one-item tuple needs the trailing comma: (5,).

Why can a tuple be a dictionary key when a list cannot?

Show the answer

A tuple is hashable because it cannot change — A key's hash must not change while it is in the dictionary, so mutable objects are refused.

Can anything about ('Ada', [1, 2]) change?

Show the answer

Yes, the list inside can be changed — A tuple fixes which objects it holds, not what those objects contain.

Next chapter

Sets

An unordered collection with no duplicates, and fast membership tests.