Skip to main content
✂️
PEP 3132 · Speedrun · Python 3.0 (2008)

PEP 3132 in 90 seconds — first, *middle, last = list

Splat-unpacking — one of Python's most-used 1-liners.

Pre-3.0, splitting an iterable into head/tail meant explicit slicing: ```python items = [1, 2, 3, 4, 5] first = items[0] middle = items[1:-1] last = items[-1] ``` Three lines, three index lookups, brittle on empty/short input. PEP 3132 (Python 3.0, 2008) added the `*` operator to assignment targets so the same split is one line:

```python first, *middle, last = [1, 2, 3, 4, 5] # first=1 middle=[2, 3, 4] last=5 ``` The starred name collects EVERYTHING the other targets didn't claim. It works in function args (`def f(head, *tail):`), in `for` loops (`for first, *rest in pairs:`), in nested unpacking (`((a, b), *rest) = ...`). It's the bones of half the iteration code in any large Python codebase — and most devs never realised it was a deliberate language-level decision.

Before — Python 2 / pre-3.0, slice-based head/tail split
items = [1, 2, 3, 4, 5]

# Manual three-line split
first = items[0]
middle = items[1:-1]
last = items[-1]

# In a function — pre-PEP-3132 you'd unpack manually too
def first_and_rest(items):
    return items[0], items[1:]
After — Python 3.0+, star-unpacking
# One line — readable, intent-explicit
first, *middle, last = [1, 2, 3, 4, 5]

# Function signatures get the same treatment
def show(head, *tail):
    return f"head={head}, tail={tail}"

# Nested — the * can sit anywhere in the target list
((a, b), *rest) = ((10, 20), 30, 40)

# In a for-loop — destructures the iterable AND the starred middle
for first, *middle, last in [(1, 2, 3), (10, 20, 30, 40, 50)]:
    print(first, middle, last)

🎯 Predict the output

What does this print? `*middle` greedy-collects everything between `first` and `last`.

first, *middle, last = [1, 2, 3, 4, 5]
print(first, middle, last)

def show(head, *tail):
    return f"head={head}, tail={tail}"
print(show(*[1, 2, 3, 4]))

((a, b), *rest) = ((10, 20), 30, 40)
print(a, b, rest)
Iterables & unpacking → Foundations track

Or speedrun another PEP

PEP 572Assignment as an expression — 3 lines become 1.
PEP 572 in 90 seconds — the walrus that ate your for-loop
PEP 484Python stays dynamic — but you can opt into typing.
PEP 484 in 90 seconds — type hints, without TypeScript-envy
PEP 622Switch statements are a 5% feature. Pattern matching is the 95%.
PEP 622 in 90 seconds — match / case isn't just a switch