Unpack Python Items

E.Y.
4 min readNov 14, 2020

--

Photo by Markus Spiske on Unsplash

For a person like me who started from JavaScript, Pack/Unpack in Python is not really a new concept, thinking about Destructuring and ES6 Spread/Rest Operator as a comparison. I’m pretty sure similar features are available in other major languages. Still, I’d like to have an overview of the Unpacking operation in Python with concrete examples — as it can be a bit bewildering for people who learn it for the first time.

So what is unpacking?

It refers to an operation that assigning an iterable value to a collection data types (e.g. tuple and dictionary). In comparison, packing is when assigning an iterable value into a single variable.

Note that when we say a collection data types we refer to both sequence and iterables. A sequence is like an ordered collection of iterables such as List, Dictionary, Tuples, Strings.

See examples below for unpacking in various scenarios:

Tuple:
>>> x, y, z= 1, 2, 3
>>> x
1
>>> y
2
>>> z
3
List
>>> x, y, z= [1, 2, 3]
>>> x
1
>>> y
2
>>> z
3
String
>>> x, y, z = '123'
>>> x
'1'
>>> y
'2'
>>> z
'3'
Dictionary -- Key>>> var_dict = {'a': 1, 'b':2, 'c': 3}
>>> x, y, z= var_dict
>>> x
'a'
>>> y
'b'
>>> z
'c'
Dictionary -- Value>>> var_dict = {'a': 1, 'b':2, 'c': 3}
>>> x, y, z= var_dict
>>> var_dict[x]
1
>>> var_dict[y]
2
>>> var_dict[z]
3
Or>>> x, y, z= var_dict.values()
>>> x
1
>>> y
2
>>> z
3
Dictionary -- Pairs>>> var_dict = {'a': 1, 'b':2, 'c': 3}
>>> x, y, z= var_dict.items()
>>> x
('a': 1)
>>> y
('b': 2 )
>>> z
('c': 3 )
Generator
>>> var = (i for i in range(3))
>>> x, y, z= var
>>> x
1
>>> y
2
>>> z
3

The above is unpacking using a single variable. The next step is unpacking using known number of values or unknown number of values.

Known Number of Values, we need to have exact number of variables to hold the number of elements in the iterable to be unpacked:

var = [1, 2, 3]
x, y, z= var
=================var = [(1, 2), 3]
x, y = var
>>> x
(1, 2)
>>> y
3
var = [(1, 2), 3]
(x, y), z = var
>>> x
1
>>> y
2
>>> z
3
var = [1, 2, 3]
x, y, _ = my_info
>>> x
1
>>> y
2

For unknown number of variables, we can use * or ** depends on if the iterable is a dictionary or not. Note that to unpack multiple values into a single variable, we need to add a comma after the * to indicate it’s a tuple/list.

The * operator for packing tuple/list/set/string/generator kind of iterable.

>>> *x, y = 1, 2, 3
>>> x
[1, 2]
>>> y
3
>>> *x, = 1, 2, 3
>>> x
[1, 2, 3]
>>> *x, y, z = 1, 2
>>> x
[]

>>> y
1
>>> z
2
>>> var = (x for x in range(3))
>>> *gen, = var
>>> gen
[1, 2, 3]

We can also use * to spread the packed iterable into another iterable (tuple/set/list).

Tuple
>>> var = (1, 2, 3)
>>> (0, *var, 4)
(0, 1, 2, 3, 4)
List
>>> var = [1, 2, 3]
>>> [0, *var, 4]
[0, 1, 2, 3, 4]
Set
>>> var = {1, 2, 3}
>>> {0, *var, 4}
{0, 1, 2, 3, 4}

For unpacking a dictionary type, we use **.

>>> var_dict = {'a': 1, 'b':2, 'c': 3}
>>> final = {**var_dict}
>>> final
{'a': 1, 'b':2, 'c': 3}

Note that when you unpack multiple dictionaries into one. The right side of the variable will overwrite the left side of variable given there are same keys:

>>> var_dict = {'a': 1, 'b':2, 'c': 3}
>>> dict_var = {"a": 4, "b":5, "d": 6}
>>> {**var_dict, **dict_var}
{'a': 4, 'b': 5, 'c': 3, 'd': 6}

Yet the most common usage of * and **, as you might have seen it already, is to define functions arguments:

>>> def fruit(any, *args, **kwargs):
print(any, *args, **kwargs)
>>> func("fruit color:", "apple", "pear", another='mango')"fruit color: apple pear mango"

As you can see apple and pear are positional arguments (), and `another='mango is keyword arguments {} that are read the value mango in the printing command.

We can also pack multiple variables in the function call (instead of function definition), note that the keyword argument has to match the key of the passed-in parameter.

>>> def fruit(any, args, another):
print(any, args, another)
>>> func("fruit color:", *["apple", "pear"], **{"another" :"mango"})"fruit color: apple pear mango"

Combine together:

>>> def fruit(any, *args, **kwargs):
print(any, args, kwargs)
>>> func("fruit color:", *["apple", "pear"], **{"another" :"mango"})"fruit color: apple pear mango"

That’s pretty much it!

Happy Reading!

--

--

No responses yet