A tuple is an ordered collection like a list, with one difference: once made, it cannot be changed.
point = (3, 4)
colour = ("crimson", 220, 20, 60)
print(point[0], point[1])
print(len(colour))
print(colour[1:])
# But changing one is an error:
point[0] = 99TypeError: 'tuple' object does not support item assignment. That is the whole
point of a tuple.
When to use which
Reach for a list when you have many of the same kind of thing and the collection will grow, shrink or be reordered: rows of data, items in a cart.
Reach for a tuple when you have a fixed number of related values that
together describe one thing: a coordinate, an RGB colour, a database row. The
position carries meaning — point[0] is the x, not just some item.
# A list of tuples: many records, each of fixed shape.
people = [
("Ada", 1815, "Mathematician"),
("Alan", 1912, "Logician"),
("Grace", 1906, "Admiral"),
]
for person in people:
print(f"{person[0]} was born in {person[1]}")Unpacking
Instead of pulling items out by index, you can assign a whole tuple to several names at once. This is where tuples start feeling elegant.
point = (3, 4)
x, y = point
print(x, y)
# The famous one-line swap - no temporary variable.
a, b = 1, 2
a, b = b, a
print(a, b)
# Unpack straight in a loop header:
people = [("Ada", 1815), ("Alan", 1912)]
for name, year in people:
print(f"{name}: {year}")for name, year in people: reads better than person[0] and person[1] ever
will, and it fails loudly if a record has the wrong shape — which is exactly
when you want to hear about it.
Starred unpacking
A *name collects everything left over.
numbers = [1, 2, 3, 4, 5]
first, *rest = numbers
print(first, rest)
*most, last = numbers
print(most, last)
head, *middle, tail = numbers
print(head, middle, tail)Returning several values
A function can only return one object — but that object can be a tuple, which in practice means Python functions return as many values as they like.
def min_and_max(values):
return min(values), max(values) # parentheses are optional
low, high = min_and_max([4, 9, 1, 7])
print(low, high)
# divmod is a built-in that does exactly this.
minutes, seconds = divmod(227, 60)
print(f"{minutes}m {seconds}s")A tuple of one needs a comma
(5) is just the number five in parentheses. (5,) is a one-item tuple. The
comma makes the tuple, not the parentheses — which is also why x = 1, 2 works
without any parentheses at all.
Before you write your own
Predict. Unpacking, then arithmetic on what came out.
order = ("tea", 2, 3.5)
item, quantity, price = order
print(f"{quantity} x {item}")
print(quantity * price)
first, *rest = [10, 20, 30]
print(first, rest)Check your prediction
2 x tea
7.0
10 [20, 30]The three names take the three positions in order. *rest always collects into
a list, even though it came from unpacking.
Fix. Each record has three parts, and the loop only names two.
people = [("Ada", 1815, "Mathematician"), ("Alan", 1912, "Logician")]
for name, year in people:
print(f"{name} was born in {year}")Check your fix
people = [("Ada", 1815, "Mathematician"), ("Alan", 1912, "Logician")]
for name, year, role in people:
print(f"{name} was born in {year}")Ada was born in 1815
Alan was born in 1912ValueError: too many values to unpack (expected 2) is Python refusing to guess
which two of the three you meant. When you don’t need a part, name it _:
for name, year, _ in people:.
Format a set of coordinates
Given a list of (name, latitude, longitude) tuples, print each city with its
hemisphere letters and no minus signs. Your output should be:
Paris: 48.9°N, 2.4°E
Lagos: 6.5°N, 3.4°E
Lima: 12.1°S, 77.0°WUse unpacking in the loop header, and one decimal place.
cities = [
("Paris", 48.86, 2.35),
("Lagos", 6.52, 3.38),
("Lima", -12.05, -77.04),
]
# Your code hereHint 1: the idea
Each tuple has three parts, so the loop header can name all three. Then two
small decisions per city: N or S depends on whether the latitude is
negative, E or W on the longitude. The number itself is printed without its
sign.
Hint 2: a first step
for name, lat, lon in cities: with print(name, lat, lon) inside. Then build
one line at a time: Day 2’s conditional expression picks a letter
("N" if lat >= 0 else "S"), and abs() removes a minus sign.
Show one solution
cities = [
("Paris", 48.86, 2.35),
("Lagos", 6.52, 3.38),
("Lima", -12.05, -77.04),
]
for name, lat, lon in cities:
ns = "N" if lat >= 0 else "S"
ew = "E" if lon >= 0 else "W"
print(f"{name}: {abs(lat):.1f}°{ns}, {abs(lon):.1f}°{ew}")abs() drops the sign once the hemisphere letter carries that information —
and the conditional expression from Day 2 picks the letter in one line each.
What you learned
- Tuples are ordered and immutable; lists are ordered and mutable.
- Use a tuple for a fixed record, a list for a varying collection.
- Unpacking assigns several names at once, including in
forheaders. *restcollects the remaining items.- Returning a tuple is how a function returns several values.