Python Basics: Giving Iterable Values Names with Unpacking
Unpacking assigns values from an iterable to several names. It can make fixed-size records easier to read and let you separate a first value, a variable middle, and a final value. The number and placement of targets describe the shape you expect.
These three standalone examples were tested on Linux with Python 3.12.14. They require no third-party packages. Assertions check the demonstrated results; run the commands normally, without Python’s -O option.
Prepare a scratch directory
You need Bash, a text editor, Python 3 on your PATH, and the mktemp, rm, and rmdir utilities. Keep using the same terminal. Save each named source file as UTF-8. The setup stops the shell if creating or entering the scratch directory fails.
start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 11. Name the fields in a fixed-size record
Save this as unpack_record.py:
record = ("notebook", 3, 250)
name, quantity, unit_cents = record
total_cents = quantity * unit_cents
assert name == "notebook"
assert total_cents == 750
print(f"Item: {name}")
print(f"Total cents: {total_cents}")
try:
name, quantity = record
except ValueError:
print("Wrong field count rejected")
else:
raise AssertionError("Expected ValueError")Run it:
python3 unpack_record.pyOutput:
Item: notebook
Total cents: 750
Wrong field count rejectedWithout a starred target, the number of values must match the number of targets. Descriptive names replace repeated numeric indexing. This checks the record length, but it does not validate the meaning or type of each field.
2. Collect the middle values with a star
Save this as unpack_middle.py:
route = ("home", "library", "cafe", "office")
start, *stops, destination = route
assert stops == ["library", "cafe"]
assert isinstance(stops, list)
print(f"Start: {start}")
print(f"Stops: {stops}")
print(f"Destination: {destination}")
start, *stops, destination = ("home", "office")
assert stops == []
print(f"Direct-route stops: {stops}")Run it:
python3 unpack_middle.pyOutput:
Start: home
Stops: ['library', 'cafe']
Destination: office
Direct-route stops: []The starred target receives a list, even though the input is a tuple. It can be empty, but this pattern still needs at least two values for start and destination. Only one starred target is allowed in this target list. Unpacking consumes the iterable; it does not leave the middle as a lazy iterator.
3. Unpack nested records in a loop
Save this as unpack_coordinates.py:
locations = [("desk", (2, 4)), ("shelf", (5, 1))]
descriptions = []
for name, (x, y) in locations:
descriptions.append(f"{name}: x={x}, y={y}")
assert descriptions == ["desk: x=2, y=4", "shelf: x=5, y=1"]
for description in descriptions:
print(description)Run it:
python3 unpack_coordinates.pyOutput:
desk: x=2, y=4
shelf: x=5, y=1Nested targets mirror the shape of each record. Each outer pair contains a name and a coordinate pair. If that shape becomes complicated, use named records or a small class instead of making readers decode a long unpacking pattern.
When to use this
Use unpacking for finite iterables whose structure you understand. A starred target may collect many values into a list, so it is unsuitable for an unbounded stream. For dictionaries, plain iteration yields keys; use items() when you want key-value pairs. See the official assignment-statement reference.
Clean up
In the same terminal, remove only the three example files, return to your original directory, and remove the empty scratch directory:
rm -- unpack_record.py unpack_middle.py unpack_coordinates.py
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dirAcknowledgements
This post was created with assistance from AI.