LambdaLabTM
Computer Science · Class 11 · Packing & Unpacking
UnpackingThe star⏱️ 11 min read

The Star: Taking the Rest

Unpacking has one demand: the counts must match. That is fine when you know how long the list is and useless when you do not. A star in front of one of the names lifts the demand — that name takes everything left over, however much or little that is.

1One name for the first, one for the rest

first_rest.py
# a star takes everything that is left over

first, *rest = [10, 20, 30, 40, 50]

print('first:', first)
print('rest: ', rest)
print('rest is a', type(rest))
Output
first: 10
rest:  [20, 30, 40, 50]
rest is a <class 'list'>
first, *rest = [...]

Two names for five items — which would normally be a ValueError. The star says 'this one is not asking for exactly one item', so the counting rule applies to the other names only.

print('rest is a', type(rest))

The starred name always ends up holding a LIST, even when the values came from a tuple or a string, and even when there is only one item in it. That is worth checking rather than assuming.

Key Takeaway
The starred name is served last, and takes what is left. Python fills every ordinary name first — one item each, in order — and only then hands the remainder to the starred one. That is why the counts no longer have to match: there is exactly one name that will accept any number of items, including none.

2Watch the star being served last

Pick first, *rest in the widget and step through it. The interesting frame is the last one, where rest is handed four items at once — and it is worth stepping the two broken cases again afterwards, to see what the star is rescuing you from.

📤 One item each, left to right

Watch the items being dealt out — and watch what happens when the counts do not match.

step 1 of 5
a, b, c = [10, 20, 30]
the names
empty
a
empty
b
empty
c
still to hand out
102030

Python checks nothing yet. It simply starts handing the items of [10, 20, 30] out to the names on the left, one each, in order.

3The star can go anywhere in the row of names

star_positions.py
# the star can go anywhere in the row of names

*most, last = [10, 20, 30, 40, 50]
print('most:', most, 'last:', last)

first, *middle, last = [10, 20, 30, 40, 50]
print('first:', first, 'middle:', middle, 'last:', last)

a, *b = [7]
print('a:', a, 'b:', b)
Output
most: [10, 20, 30, 40] last: 50
first: 10 middle: [20, 30, 40] last: 50
a: 7 b: []

Read the last line twice. a took the only item, so there was nothing left for b — and b is an empty list, not an error and not None. “Everything that is left” is a perfectly good description of nothing at all.

Watch Out
Only one star is allowed. Two of them would be ambiguous — with *a, *b = [1, 2, 3] there is no way to say where the first name should stop, and Python refuses the line with SyntaxError: multiple starred expressions in assignment.

4The ordinary names still have to be satisfied

The star relaxes the rule; it does not remove it. Every unstarred name still needs an item of its own, so a list that is too short is still an error:

still_too_few.py
# three ordinary names, two items

a, b, *c = [10, 20]

print(a, b, c)
Output
10 20 []
the same line with only one item — a, b, *c = [10]
Output
ValueError: not enough values to unpack (expected at least 2, got 1)

Note the wording: expected at least 2. Without a star it said expected 3; with one, Python knows only the minimum, and the message says so. Reading the message tells you whether a star was involved.

5Where it earns its keep

scores.py
# the winner, and everybody else

scores = [98, 91, 88, 74, 65]

winner, *others = scores

print('Winner:', winner)
print('The other', len(others), 'scores:', others)
print('Best of the rest:', max(others))
Output
Winner: 98
The other 4 scores: [91, 88, 74, 65]
Best of the rest: 91

This is the shape the star is for: one item is special and the remainder is a group — a winner and the field, a heading row and the data rows, a command and its arguments. Written with slices it would be scores[0] and scores[1:], which is perfectly fine and says less about your intention.

scores.py
Note
Not every board asks for this. Starred unpacking is ordinary modern Python and it is worth being able to read, but a Class 11 answer that needs the first item and the rest can equally say scores[0] and scores[1:]. Use whichever the question's wording suggests, and do not be surprised to meet the star in somebody else's code.

6Recap

The star takes the remainder

Ordinary names are served first, one item each, and the starred name gets whatever is left over.

It is always a list

Even from a tuple or a string, and even when it holds one item or none. An empty remainder is [], not None.

It can be first, middle or last

*most, last — first, *middle, last — first, *rest. Only one star per statement, or it would be ambiguous.

The other names still need items

a, b, *c = [10] fails with 'expected at least 2', and that wording is the clue that a star was involved.

Quick Check

a, *b = [7]. What does b hold?

Quick Check

first, *middle, last = [10, 20, 30, 40, 50]. What is middle?

Quick Check

a, b, *c = [10] raises 'not enough values to unpack (expected at least 2, got 1)'. Why 'at least'?