Skip to content
Python Basics: Giving Iterable Values Names with Unpacking

Python Basics: Giving Iterable Values Names with Unpacking

October 18, 2026

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 1

1. 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.py

Output:

Item: notebook
Total cents: 750
Wrong field count rejected

Without 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.py

Output:

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.py

Output:

desk: x=2, y=4
shelf: x=5, y=1

Nested 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_dir

Acknowledgements

This post was created with assistance from AI.

Last updated on