Python for Programmers: Unpacking
Welcome to the Unpacking lesson!
This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!
We often want to pull list and tuple elements out into their own variables. One way to do that is to assign them one by one, but that's verbose.
>
triangle_edges = (2, 3)x = triangle_edges[0]y = triangle_edges[1]hypotenuse_squared = x**2 + y**2hypotenuse_squaredResult:
13
Python offers unpacking syntax to simplify this process. We can "unpack" the elements of tuples, lists, and many other data types into their own variables on one line.
x, y = my_tupleassignsmy_tuple's first two values to the variablesxandy.(This is called "destructuring" in some other languages.)
>
triangle_edges = (2, 3)x, y = triangle_edgeshypotenuse_squared = x**2 + y**2hypotenuse_squaredResult:
13
>
coordinates = [2, 3, 4]x, y, z = coordinateszResult:
4
We have to unpack the exact number of elements that are in the list or other data source. Otherwise, we get a
ValueError.>
guests = ["Amir", "Betty", "Cindy"]first, second = guestsfirst, secondResult:
ValueError: too many values to unpack (expected 2)
>
coordinates = (2, 3)x, y, z = coordinatesxResult:
ValueError: not enough values to unpack (expected 3, got 2)
Sometimes we only need some of the elements. The community convention is to unpack unneeded elements into a variable named
_. Using_clearly communicates that we don't care about that value right now.>
coordinates = (2, 3, 4)x, _, z = coordinatesx + zResult:
6
We can use
_multiple times when there are multiple values that we don't care about.>
coordinates = (2, 3, 4)_, y, _ = coordinatesyResult:
3
The
_variable is a regular variable, and it does get a value. This is purely a convention: we all agree that we'll only use the_variable to store values that we don't actually use.>
coordinates = (2, 3, 4)x, _, z = coordinates# It's possible to read the `_` variable, but don't do it!_Result:
3
Unpacking leads to a common shortcut for assigning multiple variables. It works by combining unpacking with a feature we saw in another lesson: we can create a tuple by separating values with commas, without parentheses.
By combining these two features, we can write statements like
x, y = 1, 2. This is the same asx = 1followed byy = 2.>
x, y = 2 + 1, 3 * 3x, yResult:
(3, 9)
We can unpack many values at once by "starring" a variable name, like
*rest. Infirst, *rest = [1, 2, 3],firstgets the first value, andrestgets all remaining values. Variables receiving multiple values like*restpack the values into a list.>
first, *rest = ["a", "b", "c"]restResult:
>
first, second, *rest = [1, 2, 3, 4]restResult:
[3, 4]
*restis called a "starred expression". We can use starred expressions anywhere in the unpacking expression. Python uses the non-starred names to decide which values go in the starred expression.>
first, *middle, last = ["a", "b", "c", "d"]middleResult:
['b', 'c']
>
front, *middle, end = [1, 2, 3, 4, 5, 6]len(middle)Result:
4
There can only be one starred name in the variable list. Trying to use multiple raises a
SyntaxError.>
first, *some, middle, *more, last = [1, 2, 3, 4, 5, 6]moreResult:
SyntaxError: multiple starred expressions in assignment (<string>, line 1)
We can combine starred expressions with
_to ignore the rest of the iterable.>
first, second, *_ = [6, 3, 2, 1, 4]first + secondResult:
9
We can use [square brackets] on the left side of an unpacking statement. This doesn't affect the unpacking behavior, but it can be a useful hint to other people reading the code later: "the thing that we're unpacking is a list, not a tuple."
>
coordinates = [2, 3][x, y] = coordinatesx + yResult:
5
At runtime, Python evaluates the right side of an assignment statement first. Then it does the assignments on the left side. This lets us do tricks like swapping out values in the same expression, without the intermediary step required in many other languages.
>
x = 1y = 2# In most languages, we'd have to use an intermediate variable when swapping# two variables' values, like this.temp = xx = yy = tempx, yResult:
(2, 1)
>
x = 1y = 2# In Python, we can swap with a single unpacking assignment statement.x, y = y, xx, yResult:
(2, 1)
So far we've unpacked lists and tuples. We can also unpack any other iterable. For example, we can unpack dictionaries. Iterating over dictionaries gives us the keys, so unpacking also gives us the keys.
(Python remembers dictionary keys' insertion order, so the keys in the next example will come out in the order they were defined.)
>
some_dict = {"a": 1,"b": 2,}x, y = some_dict(x, y)Result:
('a', 'b')Unpacking syntax also works in
forloops. It often shows up when iterating over lists that contain tuples.Suppose that we want to iterate over a list of tuples representing x-y coordinates, like
[(2, 3), ...]. If we don't use unpacking syntax, we have to explicitly accesscoord[0]andcoord[1]in the code.>
coordinates = [(2, 3), (5, 2)]total = 0for coord in coordinates:x = coord[0]y = coord[1]total += x * ytotalResult:
16
Unpacking gives us a cleaner version: we can unpack into
x, yright in theforloop itself.>
coordinates = [(2, 3), (5, 2)]total = 0for x, y in coordinates:total += x * ytotalResult:
16
Unpacking leads to a lot of small code savings like this, which add up to make our code more readable!