Extended iterable unpacking PREMIUM

Trey Hunner smiling in a t-shirt against a yellow wall
Trey Hunner
3 min. read Watch as video Python 3.10—3.14
Python Morsels
Watch as video
02:49

Let's talk about extended iterable unpacking.

Tuple unpacking describes the size of the iterable you're unpacking

Tuple unpacking is great when you know the size of the iterable you're unpacking.

For example, here we're unpacking a three-item tuple (called coordinates) into three variables:

>>> coordinates = (3, 4, 5)
>>> x, y, z = coordinates

But what if we don't know the size of the iterable we're unpacking?

Here we're unpacking a list of many numbers into three variables:

>>> numbers = [2, 1, 3, 4, 7, 11, 18]
>>> first, second, rest = numbers

What do you think we'll get from this unpacking?

What will first, second, and rest be after this unpacking?

>>> first, second, rest = numbers

It turns out we get an error when we try to unpack numbers into three variables:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 3)

The number of variables we're unpacking into has to be the same as the number of items in the iterable we're unpacking. By unpacking into three variables we were implicitly asserting that there are three items in numbers, but there are more than three items in numbers so our unpacking failed.

Since we're working with a list here we could get around this by slicing our list. We could slice this list twice to get the first two items and then everything after those items and put those in a tuple and then use deep unpacking:

>>> numbers = [2, 1, 3, 4, 7, 11, 18]
>>> (first, second), rest = numbers[:2], numbers[2:]

And this works: we end up with first and second pointing to the first two items and rest pointing to the remaining values:

>>> first
2
>>> second
1
>>> rest
[3, 4, 7, 11, 18]

But there's a better way to do this; instead we can use extended iterable unpacking.

Extended iterable unpacking can unpack iterables with an unknown size

Extended iterable unpacking involves using Python's prefix * operator:

>>> numbers = [2, 1, 3, 4, 7, 11, 18]
>>> first, second, *rest = numbers

That * allows us to capture the remaining values into a list:

>>> rest
[3, 4, 7, 11, 18]

Python always captures those remaining values into a list; even if the iterable we're unpacking isn't a list.

The limitations of extended iterable unpacking

This * syntax is pretty nifty, but what are the limitations of it?

Could we put a * at the beginning of our tuple unpacking? What's your guess?

>>> numbers = [2, 1, 3, 4, 7, 11, 18]
>>> *first, last = numbers

This actually works.

Python captured everything but the last item into our first variable:

>>> first
[2, 1, 3, 4, 7, 11]
>>> last
18

Could we put the * in the middle of our tuple unpacking?

>>> numbers = [2, 1, 3, 4, 7, 11, 18]
>>> first, second, *middle, last = numbers

This works as well. That middle variable includes everything except the first two values and the last value:

>>> middle
[3, 4, 7, 11]

Could we use two stars (*) in tuple unpacking?

>>> numbers = [2, 1, 3, 4, 7, 11, 18]
>>> a, *b, *c, d = numbers

We can't. You can only use one * in tuple unpacking:

>>> a, *b, *c, d = numbers
  File "<stdin>", line 1
SyntaxError: multiple starred expressions in assignment

As long as there's just one * operator, Python will figure out what you meant.

Getting rid of hard-coded indexes and hard-coded slices

If something is important, it deserves a name.

Tuple unpacking is great when you're trying to get rid of hard-coded indexes:

coordinates = (3, 4, 5)

x = coordinates[0]
y = coordinates[1]
z = coordinates[2]

And give names to things instead:

coordinates = (3, 4, 5)

x, y, z = coordinates

But you can also sometimes use tuple unpacking to get rid of hard-coded slices:

numbers = [2, 1, 3, 4, 7, 11, 18]

first = numbers[0]
rest = numbers[1:]

By using a * operator in tuple unpacking to capture the remaining values as you're unpacking:

numbers = [2, 1, 3, 4, 7, 11, 18]

first, *rest = numbers

Summary

So tuple unpacking is great when you know the size of the iterable that you're unpacking. But if you don't know the size of the iterable you're unpacking and you'd like to capture the remaining values into a list you can use extended iterable unpacking by putting a star (*) before the variable that's supposed to capture those remaining values.

Series: Tuple Unpacking

It's tempting to reach for indexes when working with tuples, lists, and other sequences, but if we know the shape of the tuple we're working with, we can unpack it instead.

Tuple unpacking (aka "multiple assignment" or "iterable unpacking") is often underutilized by new Python programmers.

To track your progress on this Python Morsels topic trail, sign in or sign up.

0%
Python Morsels
Watch as video
02:49
This is a free preview of a premium screencast. You have 2 previews remaining.