Tuples and unpacking
A list that cannot change, where that is exactly what you want, unpacking so you use names instead of indexes, swapping in one line, and the (5) versus (5,) trap.
- 1Encounter
- 2Understand
- 3Worked
- 4Predict
- 5Apply
- 6Stretch
The problem we are solving
Three days of weather need recording — for each day the name, the temperature and the humidity.
A list does the job: ["monday", 31.5, 78]. It works, and two things nag.
First, that list can be changed. If something appends to Monday's record by mistake, Python will not say a word — even though a record was never supposed to have four things in it. Putting something that must not change into a container that can be changed is a quiet risk.
Second, getting the three values back out means writing record[0], record[1], record[2] — by number, not by name. Six months later, nobody reading record[1] will know whether that is the temperature or the humidity.
A tuple answers both: it is a list that cannot be changed — and it brings an ability called unpacking, which lets you use names instead of indexes.
By the end of this chapter you can
- Build a tuple, and say where a tuple is right and a list is not
- Put several values into several names at once with unpacking
- Swap two variables in a single line
- Tell
(5)from(5,) - Explain why
appendon a tuple raises anAttributeError
Prerequisites: Sorting lists, and the methods that come with them.
A tuple — a list that cannot be changed
Round brackets instead of square ones:
point = (3, 7)
print(point)
print(point[0])
print(len(point))(3, 7)
3
2Reading, indexing, len, slicing, in, walking with for — everything you did to a list works. There is one difference, and it is the whole thing:
point = (3, 7)
point[0] = 5TypeError: 'tuple' object does not support item assignmentDoes that message look familiar? It is word for word what chapter six gave when a character inside text was changed, with 'str' in place of 'tuple'. Python's immutable things all complain in the same language.
The methods that change things are absent too:
point = (3, 7)
point.append(9)AttributeError: 'tuple' object has no attribute 'append'An AttributeError means "this kind of thing has no such method". A tuple cannot be changed, so it simply does not have the methods that change things — an AttributeError rather than a TypeError, because the problem is the object, not the operation.
Why this is an advantage, not a limitation
At first a tuple looks like a list with features removed. Turn it round: if something is not supposed to change, putting it somewhere it cannot change stops the mistake before it happens.
There is no sense in adding a third number to the coordinate (3, 7). A date (2026, 9, 16) has no fourth part. Held in tuples, those accidents arrive as errors immediately instead of as bugs later.
As a rule: a fixed number of things, each meaning something different — tuple. An unknown number of things, all of the same kind — list.
So three days of weather is tuples inside a list: the number of days is not known (a list), but every record holds exactly three things (a tuple).
Unpacking — where the real benefit is
point = (3, 7)
x, y = point
print(x)
print(y)3
7Two names and two values on one line. And now it is y rather than point[1] — a name that explains itself when read.
There have to be as many names on the left as there are values on the right:
point = (3, 7)
x, y, z = pointValueError: not enough values to unpack (expected 3, got 2)That message is unusually helpful — it tells you both how many were expected and how many arrived.
Unpacking is not limited to tuples; it works on lists too. It is most useful with tuples because that is where the number of values is known in advance.
Swapping, in one line
Other languages need a temporary third variable to exchange two values. Python does not:
a = 1
b = 2
a, b = b, a
print(a, b)2 1How the line works is worth understanding: Python evaluates the whole right-hand side first, building a tuple (2, 1), and then unpacks it into the left. So although a changes, b's old value has already been captured, and nothing is lost.
The brackets are not actually required
point = 3, 7
print(point)
print(type(point))(3, 7)
<class 'tuple'>What makes a tuple is the comma, not the brackets. The brackets are there for readability. Once you know that, a, b = b, a stops looking like magic — b, a on the right is simply a tuple.
And out of that comes a trap:
one = (5)
really = (5,)
print(type(one))
print(type(really))
print(len(really))<class 'int'>
<class 'tuple'>
1(5) is not a tuple — it is a number in brackets, exactly like (2 + 3). Building a tuple of one value requires the comma: (5,). It looks like a typo, and that comma is the entire difference.
Tuples in a loop
people = [("rafi", 22), ("ahmed", 35)]
for name, age in people:
print(f"{name} is {age}")rafi is 22
ahmed is 35for name, age in people unpacks each tuple straight into two names. No person[0] and person[1] — and the code says what it means when you read it.
You have used this already without knowing:
stock = ["pen", "bag"]
for pair in enumerate(stock):
print(pair)(0, 'pen')
(1, 'bag')enumerate hands back tuples. Writing for position, item in enumerate(...) in the last chapter was unpacking them — we just had no name for it.
Converting between the two
as_list = [3, 7]
as_tuple = (3, 7)
as_list.append(9)
print(as_list)
print(as_tuple)
print(list(as_tuple))
print(tuple(as_list))[3, 7, 9]
(3, 7)
[3, 7]
(3, 7, 9)list() and tuple() build one from the other — a new thing each time, leaving the original alone. That is how you "change" a tuple: make a list, change it, make a tuple again.
A complete example
weather.py:
# A tuple is the right shape for a record that must not change
readings = [
("monday", 31.5, 78),
("tuesday", 33.0, 71),
("wednesday", 29.5, 85),
]
print("Day Temp Humidity")
for day, temp, humidity in readings:
print(f"{day:<10} {temp:>5} {humidity:>5}")
hottest = readings[0]
for reading in readings:
if reading[1] > hottest[1]:
hottest = reading
day, temp, humidity = hottest
print()
print(f"Hottest was {day} at {temp}")
temps = []
for _, temp, _ in readings:
temps.append(temp)
print("Temps :", temps)
print("Average :", round(sum(temps) / len(temps), 2))Day Temp Humidity
monday 31.5 78
tuesday 33.0 71
wednesday 29.5 85
Hottest was tuesday at 33.0
Temps : [31.5, 33.0, 29.5]
Average : 31.33Four things worth noticing.
A list on the outside, tuples on the inside. The number of days can grow, so the outer thing is a list. Every record holds exactly three things, so the inner ones are tuples. This is the most common shape real data comes in.
f"{day:<10}" and f"{temp:>5}" keep the columns straight. < aligns left, > aligns right, and the number says how much width to occupy. Like chapter six's :.2f, everything after the colon is formatting.
Finding the hottest day needed reading[1], because during the comparison the whole tuple is in hand rather than an unpacked one. It is unpacked as soon as it is found — which is why the line after has no indexes in it.
for _, temp, _ in readings — the underscore is a convention meaning "I do not need this one". To Python it is an ordinary name; to a reader it says which parts are being deliberately thrown away.
When it breaks
TypeError: 'tuple' object does not support item assignment An attempt to change a value inside a tuple. Tuples cannot be changed — either use a list from the start, or convert with list(...), change it, and convert back.
AttributeError: 'tuple' object has no attribute 'append' The same cause wearing different clothes. No changing method — append, remove, sort — exists on a tuple. sorted(my_tuple) does work, because it returns a new list and leaves the tuple alone.
ValueError: not enough values to unpack (expected 3, got 2) There are more names on the left than values on the right. print(len(record)) shows how many are actually in there.
ValueError: too many values to unpack (expected 2) The opposite — more values than names.
I made a tuple of one value and it is not a tuple The comma is missing. (5) is a number; (5,) is a tuple.
A list inside my tuple changed A tuple protects its own structure — which things are in it cannot change. But if one of those things is itself changeable, such as a list, the inside of that list can still change. In ([1, 2], 3) you can append to the first list.
Step 4 of 6 — Predict
Check your understanding
What is printed after the unpacking?
point = (3, 7)
x, y = point
print(y, x)- A7 3
- B3 7
- C(3, 7)
- DA `ValueError`
An attempt to append to a tuple. Which error comes, and why that one?
point = (3, 7)
point.append(9)- AAn `AttributeError` — a tuple cannot change, so the changing methods simply do not exist on it
- BA `TypeError` — `append` is not allowed on a tuple
- CNothing happens; the tuple is unchanged
- DA `ValueError`
The two lines differ by one comma. What does type() report?
one = (5)
really = (5,)
print(type(one))
print(type(really))- A<class 'int'> <class 'tuple'>
- B<class 'tuple'> <class 'tuple'>
- C<class 'int'> <class 'int'>
- D<class 'tuple'> <class 'int'>
Answering needs an account
Sign in to check your answers
The questions are above, and working them out in your head is the part that matters. Sign in to see the answers, the explanations and the three-level hints.
Your turn
Write a file called contacts.py holding a list of at least five people, each one a tuple of a name, an age and a favourite subject.
Then:
- Print everyone in aligned columns, using
for name, age, subject in contacts: - Find the oldest person, unpack them, and print one sentence about them
- Build a list of just the names, and print it on one line with
join - Print the average age
- Swap two variables in a single line and show it worked
Then break it three times on purpose, and read each message:
- Try to change the age inside one of the tuples
- Try to
appendto a tuple - Try to unpack a three-value tuple into two names
Three different errors will come back — TypeError, AttributeError, ValueError. Being able to explain to yourself which is which, and why, means tuples are yours.
Step 6 of 6
Stretch — the chapter quiz
Ten questions from easy to hard. The last ones are difficult on purpose.
Sign in to take the quiz