Python Part I · Module 6 · Tuples
Unpacking a Tuple Into Names
A tuple is a record whose positions have meaning, and position numbers do not carry that meaning very well. Code that says job[0] and job[1] makes the reader hold the field order in their head, and makes every line wrong the day a field is inserted. Python lets you take the record apart into named pieces in a single line, and the result reads like what it is. The syntax looks like a special feature and is not — it is ordinary assignment with more than one name on the left, and once you see it that way, everything else in this chapter, including the two errors and the famously neat way to swap two values, follows without further rules.
Foundation13 min readPythonPart IFundamentalsTuplesUnpacking
Part I · Module 6 · Chapter 6.5 · Unpacking a Tuple Into Names
1. The Problem With Position Numbers
Here is a job, and the honest way to read its parts with what you knew before this chapter:
job = ("axi_burst", 4210)
test = job[0]
seed = job[1]
print(test, seed)axi_burst 4210That works. It is also two lines of bookkeeping, and job[0] tells a reader nothing — they have to already know that position 0 is the test name. Chapter 5.7 flagged exactly this cost for nested lists.
Python does it in one line:
job = ("axi_burst", 4210)
test, seed = job
print(test)
print(seed)axi_burst
4210Two names on the left, one tuple on the right, and afterwards test refers to "axi_burst" and seed refers to 4210. This is called unpacking.
2. What Is Actually Happening
It looks like special syntax. It is not, and seeing why makes everything else predictable.
Assignment has always been "work out the right-hand side, then make the left-hand side refer to it". Unpacking is that with more than one target:
- The right side is evaluated and produces a collection of values — here, a tuple of two.
- The left side offers a number of names — here, two.
- Python pairs them by position: first value to first name, second value to second name.
That is the whole mechanism. test, seed = job means "this thing has two parts; call the first one test and the second one seed."
Note also that the comma on the left is doing the same job the comma on the right did in Chapter 6.1. There, a comma grouped values into a tuple; here, a comma groups names into targets. Python is consistent about what a comma means.
Three fields work exactly the same way, and each name gets the element's own type:
rec = ("smoke", "PASS", 12.4)
name, status, runtime = rec
print(name, status, runtime)
print(type(runtime))smoke PASS 12.4
<class 'float'>runtime is a float, ready for arithmetic. Nothing was converted or wrapped — unpacking hands over the elements themselves.
3. Packing Is the Same Comma
The reverse operation has a name too, and you have already used it. Chapter 6.1 showed this:
point = 10, 20
print(point, type(point))(10, 20) <class 'tuple'>Collecting several values into one tuple is packing. Together they are a matched pair:
point = 10, 20
x, y = point
print(x, y)10 20Pack on one line, unpack on the next, and you are back to two separate names. Which makes the shape of a lot of real Python clear: a tuple is how several values travel together, and unpacking is how they stop travelling together at the other end.
4. It Works on Any Ordered Collection
Nothing about unpacking is tuple-specific — it needs only something that supplies values in order. A list works:
pair = ["clk", 1]
sig, width = pair
print(sig, width)clk 1And so does a string, which supplies characters:
a, b, c = "abc"
print(a, b, c)a b cThat last one is rarely useful and is worth seeing once, because it confirms the mechanism rather than introducing an exception. Chapter 5.9's word for "supplies values in order" was iterable, and unpacking works on any of them.
5. When the Counts Do Not Match
Both failures come straight from step 3 of Section 2, and both messages are unusually helpful.
More values than names:
a, b = (1, 2, 3)ValueError: too many values to unpack (expected 2)Fewer values than names:
a, b, c = (1, 2)ValueError: not enough values to unpack (expected 3, got 2)Read that second message: expected 3, got 2. It tells you how many names you offered and how many values arrived, which is usually enough to find the bug without printing anything. The one-element case says the same thing:
a, b = (1,)ValueError: not enough values to unpack (expected 2, got 1)These are ValueError, not TypeError — the value was the right kind of thing, there was just the wrong number of parts in it. Compare with handing over something that has no parts at all:
a, b = 5TypeError: cannot unpack non-iterable int objectTypeError this time, and "non-iterable" is Chapter 5.9's word again: a single number has no contents to distribute among two names.
6. Paired Data in a Loop
This is the use the canonical curriculum names for this chapter, and it is where unpacking earns its place.
Chapter 5.4 taught you to go through a list. When the elements of that list are records, each pass hands you a whole record — and unpacking turns it into named fields:
jobs = [("smoke", 1), ("reset", 2), ("burst", 3)]
for job in jobs:
test, seed = job
print(test, seed)smoke 1
reset 2
burst 3Read the body: the loop gives you one job per pass, the unpacking line names its two parts, and the rest of the body talks about test and seed rather than job[0] and job[1]. On a three-line body the saving is small; on a twenty-line body it is the difference between readable and not.
A list of tuples like this is an extremely common shape — it is how paired data usually arrives, and Module 8 will show the structure that often replaces it.
7. Two Idioms Worth Knowing
Swapping two values
Because the right-hand side is fully evaluated before any name is assigned, this works and needs no temporary name:
p, q = 1, 2
print(p, q)
p, q = q, p
print(p, q)1 2
2 1The line p, q = q, p packs the current values into a tuple (2, 1), then unpacks it into p and q. Nothing is overwritten halfway, because the packing happens first. In many languages this needs three lines and a temporary variable.
Ignoring a field
When you only want some of the parts, the convention is to unpack into a name called _:
_, only_seed = ("axi_burst", 4210)
print(only_seed)4210_ is an ordinary name — there is no special syntax here — but Python programmers use it to mean "a value I am required to name and do not intend to use". A reader seeing _ knows to ignore that field. You still have to supply a name for every position, because the counts must match.
8. Predict, Run, Observe
Predict every line before reading on. Two of these raise.
rec = ("clk", 1, "input")
a, b, c = rec
print(b)
x, y = ("PASS", 12.4)
print(type(y))
m, n = [3, 4]
print(m + n)
print(("a", "b") == ("b", "a"))The verified output:
1
<class 'float'>
7
FalseNothing raised after all — all three unpackings had matching counts. b is 1, the second field. y is a float because that is what the element is. m + n is 7 because unpacking a list hands over the numbers themselves, so this is ordinary arithmetic.
Now the two that do raise, and predict the exact message for each:
a, b = ("clk", 1, "input")ValueError: too many values to unpack (expected 2)a, b, c = ("clk", 1)ValueError: not enough values to unpack (expected 3, got 2)Three values into two names, then two values into three names. The second message names both counts; the first names only the expectation, because it stopped as soon as it had one value too many.
9. Exercises
Exercise 1 — unpack a record. For sig = ("reset_n", 1, "input"), write the one line that gives you three names, then print each. Say in one sentence why this is better than three indexed assignments.
Exercise 2 — pack then unpack. Write a line that packs a test name and a runtime into one tuple without using parentheses, then a line that unpacks it into two names. Print the type of the packed value to confirm.
Exercise 3 — predict the error. For each, say whether it succeeds and, if not, give the exact error message:
(a) a, b = (1, 2) (b) a, b = (1, 2, 3) (c) a, b, c = (1, 2) (d) a, b = [1, 2] (e) a, b = "xy" (f) a, b = 7
Exercise 4 — read the message. A script fails with ValueError: not enough values to unpack (expected 3, got 2). Explain in two sentences what the two numbers mean and what you would check first.
Exercise 5 — the swap. Explain in two sentences why p, q = q, p works without a temporary name, referring to the order in which the two sides are evaluated.
Exercise 6 — loop over pairs. Given results = [("smoke", "PASS"), ("reset", "FAIL")], write a loop that prints each test name and its status on one line, using unpacking inside the body. Use only the loop form from Chapter 5.4.
Exercise 7 — ignore a field. Rewrite seed = ("axi_burst", 4210)[1] using unpacking and the _ convention, and say in one sentence what _ tells a reader.
Exercise 8 — count mismatch as a safeguard. A record gains a fourth field. Explain in two sentences what happens to code written as a, b, c = rec versus code written as rec[0], rec[1], rec[2], and which you would rather have.
10. Summary
- Unpacking assigns a collection's elements to several names at once.
test, seed = job. - It is ordinary assignment with more than one target, not special syntax: the right side is evaluated, the left side offers names, and they are paired by position.
- Packing is the same comma in reverse —
point = 10, 20builds a tuple. Pack to travel together, unpack to arrive. - Each name gets the element's own type, ready to use.
- It works on any iterable — tuples, lists, strings — but a tuple is the natural source, because unpacking requires a known number of parts.
- The counts must match.
ValueError: too many values to unpack (expected 2)ornot enough values to unpack (expected 3, got 2), which names both numbers. - Unpacking something with no parts is
TypeError: cannot unpack non-iterable int object. - The count check is a safeguard, failing immediately and precisely when a record's shape changes.
- In a loop over paired data, unpack the record inside the body to get readable field names. The shorter loop-header form belongs to Module 10.
p, q = q, pswaps two values because the right side is fully evaluated before anything is assigned._is a conventional name for a field you must name but will not use.
Two chapters remain: what a tuple can do, and when to choose one.
Where this fits
Part of the Python curriculum.
