Execute Program

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**2
    hypotenuse_squared
    Result:
    13Pass Icon
  • 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_tuple assigns my_tuple's first two values to the variables x and y.

  • (This is called "destructuring" in some other languages.)

  • >
    triangle_edges = (2, 3)
    x, y = triangle_edges
    hypotenuse_squared = x**2 + y**2
    hypotenuse_squared
    Result:
    13Pass Icon
  • >
    coordinates = [2, 3, 4]
    x, y, z = coordinates
    z
    Result:
    4Pass Icon
  • 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 = guests
    first, second
    Result:
    ValueError: too many values to unpack (expected 2)Pass Icon
  • >
    coordinates = (2, 3)
    x, y, z = coordinates
    x
    Result:
    ValueError: not enough values to unpack (expected 3, got 2)Pass Icon
  • 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 = coordinates
    x + z
    Result:
    6Pass Icon
  • We can use _ multiple times when there are multiple values that we don't care about.

  • >
    coordinates = (2, 3, 4)
    _, y, _ = coordinates
    y
    Result:
    3Pass Icon
  • 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:
    3Pass Icon
  • 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 as x = 1 followed by y = 2.

  • >
    x, y = 2 + 1, 3 * 3
    x, y
    Result:
    (3, 9)Pass Icon
  • We can unpack many values at once by "starring" a variable name, like *rest. In first, *rest = [1, 2, 3], first gets the first value, and rest gets all remaining values. Variables receiving multiple values like *rest pack the values into a list.

  • >
    first, *rest = ["a", "b", "c"]
    rest
    Result:
  • >
    first, second, *rest = [1, 2, 3, 4]
    rest
    Result:
    [3, 4]Pass Icon
  • *rest is 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"]
    middle
    Result:
    ['b', 'c']Pass Icon
  • >
    front, *middle, end = [1, 2, 3, 4, 5, 6]
    len(middle)
    Result:
    4Pass Icon
  • 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]
    more
    Result:
    SyntaxError: multiple starred expressions in assignment (<string>, line 1)Pass Icon
  • We can combine starred expressions with _ to ignore the rest of the iterable.

  • >
    first, second, *_ = [6, 3, 2, 1, 4]
    first + second
    Result:
    9Pass Icon
  • 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] = coordinates
    x + y
    Result:
    5Pass Icon
  • 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 = 1
    y = 2

    # In most languages, we'd have to use an intermediate variable when swapping
    # two variables' values, like this.
    temp = x
    x = y
    y = temp

    x, y
    Result:
    (2, 1)Pass Icon
  • >
    x = 1
    y = 2

    # In Python, we can swap with a single unpacking assignment statement.
    x, y = y, x

    x, y
    Result:
    (2, 1)Pass Icon
  • 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')Pass Icon
  • Unpacking syntax also works in for loops. 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 access coord[0] and coord[1] in the code.

  • >
    coordinates = [(2, 3), (5, 2)]
    total = 0
    for coord in coordinates:
    x = coord[0]
    y = coord[1]
    total += x * y
    total
    Result:
    16Pass Icon
  • Unpacking gives us a cleaner version: we can unpack into x, y right in the for loop itself.

  • >
    coordinates = [(2, 3), (5, 2)]
    total = 0
    for x, y in coordinates:
    total += x * y
    total
    Result:
    16Pass Icon
  • Unpacking leads to a lot of small code savings like this, which add up to make our code more readable!