Python Unpacking

Introduction

The Python unpacking syntax allows you to extract elements from iterable objects such as lists, tuples, and dictionaries and assign them to individual variables. The unpacking feature not only simplifies code but also enhances readability, making it a great tool for the Python programmer.

The Basic Python Unpacking Syntax

You can assign the elements of an iterable to individual variables using a simple syntax that includes a comma-separated list of variables on the left, that’s assigned with an equal sign = to the iterable object on the right.

my_list = [1, 2, 3]
first, second, third = my_list
print(f"'first' holds {first}, 'second' holds {second}, and 'third' holds {third}.")

Output:

'first' holds 1, 'second' holds 2, and 'third' holds 3.

In this example, the list my_list, which contains three items, is unpacked into the three first, second, and third variables. Each variable is assigned the corresponding item’s value. After this operation, first holds 1, second holds 2, and third holds 3.

Unpacking With an Asterisk (*) – Extended Unpacking

Python also allows for extended unpacking using the asterisk * operator. Extended unpacking lets you capture some items into individual variables while placing all the rest in a separate list. This is particularly useful when dealing with collections that contain a varying numbers of elements.

Example:

my_list = [1, 2, 3, 4, 5]
first, second, *rest = my_list
print(f"The first two items are {first} and {second} and the rest are {rest}.")

Output:

The first two items are 1 and 2 and the rest are [3, 4, 5].

In this example, first and second capture the first two items, while rest captures the remaining ones as a list, [2, 3, 4, 5]. The asterisk operator signals that all remaining elements should be assigned to the variable, regardless how many there are.

The remaining items that * captures will end up as a Python list regardless of the type of iterable being unpacked.

my_string = "I'm a string."
char1, char2, *rest = my_string
print(f"The first two characters are `{char1}` and `{char2}` and the rest are {rest}.")

Output:

The first two characters are `I` and `'` and the rest are ['m', ' ', 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', '.'].

In the example above, the iterable is a string, but the rest variable ends up as a list of characters.

It’s also possible to capture one or more individual items from the start of the iterable by placing the asterisk first.

my_list = [1, 2, 3, 4, 5]
*rest, last = my_list
print(f"The last item is {last} and the rest are {rest}.")

Output:

The last item is 5 and the rest are [1, 2, 3, 4].

And finally, you can capture items from the start and end, and place the remaining middle portion in the list.

Example:

my_list = [1, 2, 3, 4, 5]
first, *rest, last = my_list
print(f"The first item is {first}, the last item is {last}, and the middle portion is {rest}.")

Output:

The first item is 1, the last item is 5, and the middle portion is [2, 3, 4].

Unpacking Nested Iterable Objects

Unpacking can also be applied to nested iterables, i.e., iterables whose items are also iterables. You can do this type of unpacking with parentheses (), which allow you to access items at multiple levels of nesting.

nested_list = [1, [2, 3], 4]
first, (second, third), fourth = nested_list
print(f"The items are {first}, {second}, {third}, and {fourth}.")

Output:

The items are 1, 2, 3, and 4.

In this case, first will be 1, second will be 2, third will be 3, and fourth will be 4. Nested unpacking can be a powerful tool for working with complex data structures.

Unpacking Dictionaries

Unpacking dictionaries works the same way as unpacking other iterables. However, dictionaries have the items(), keys(), and values() methods that return iterators for key-value pairs, keys, and values, respectively. You can use each of those methods to unpack the type of dictionary information you want.

my_dict = {'a': 1, 'b': 2, 'c': 3}
(key1, value1), (key2, value2), (key3, value3) = my_dict.items()
print(f"The key-value pairs in this dictionary are {key1}/{value1}, {key2}/{value2}, and {key3}/{value3}.")

Output:

The key-value pairs in this dictionary are a/1, b/2, and c/3.

The example above uses the nested unpacking syntax to unpack the dictionary key-value pairs iterable, returned by the items() method, all into separate variables.

Summary & Reference for Python Unpacking

Python unpacking is a technique for extracting and assigning elements from iterable objects like lists, tuples, and dictionaries to individual variables.


You can assign the elements of an iterable to individual variables using syntax that includes a comma-separates list of variables on the left, that’s assigned with an equal sign = to the iterable object on the right.

my_list = [1, 2, 3]
first, second, third = my_list  # first -->  1  second --> 2  third --> 3

Extended unpacking with the * operator separates some elements into variables while collecting the rest in a Python list.

my_list = [1, 2, 3, 4, 5]
first, second, *rest = my_list  # first --> 1  second --> 2  rest --> [3, 4, 5]
first, *rest, fifth = my_list   # first --> 1  rest --> [2, 3, 4]  fifth --> 5
*rest, fourth, fifth = my_list  # rest --> [1, 2, 3]  fourth --> 4  fifth --> 5

Unpacking extends to nested iterable, granting access to elements at multiple levels of nesting using parentheses ().

nested_list = [1, [2, 3], 4]
first, (second, third), fourth = nested_list  # first --> 1  second --> 2  third --> 3  fourth --> 4

Dictionaries have the items(), keys(), and values() methods that return iterators for the key-value pairs, keys, and values, respectively. You can use the unpacking syntax with each, but with items(), you can also use the nested unpacking syntax to assign keys and values to individual variables.

my_dict = {'a': 1, 'b': 2, 'c': 3}
(key1, value1), (key2, value2), (key3, value3) = my_dict.items()  # key1 --> 'a'  value1 --> 1  key2 --> 'b'  value2 --> 2  key3 --> 'c'  value3 --> 3