5 min read

Unpacking Iterables in Python

Learn different ways to unpack iterables or sequences in Python through useful examples.
Unpacking Iterables in Python
Unpacking iterables and sequences in Python

You can easily unpack sequences or iterables into various variables in python.

Table of Content

  1. Difference between Sequences and Iterables?
  2. Basic Unpacking of iterables and Sequences
  3. Unpacking known length iterables
  4. Unpacking Sequence within a Sequence
  5. How to discard values while unpacking?
  6. How to unpack a Python dictionary?
  7. Unpacking arbitrary length iterables
  8. How to skip header in a CSV in Python?

Difference between Sequences and Iterables?

A sequence is an ordered collection of values. Once a list is initialized, the index of the values will not change. Some examples of sequences are List, Dictionary, Tuples, and Strings.

Iterables are a collection of values over which you can loop over. All sequences are iterables, but not all iterables are sequences. For example, Sets.

x = {12, 6, 9}
print(x)

# Result
>> {6, 9, 12}

So the order in which the values in the set are initialized is not the way it appears. Also, Sets return only unique elements.

x = {12, 6, 9, 9}
print(x)

# Result
>> {6, 9, 12}

Basic Unpacking

You can carry out the unpacking procedure for all kinds of iterables like lists, tuples, strings, iterators and generators.

There are 2 ways to unpack iterables in Python.

  1. For known length iterables - Providing the exact number of variables to unpack as the number of elements in the sequence/iterable.
  2. For arbitrary length iterables - Using star expressions (*) to unpack when you are unsure of the number of variables to pass.

Let’s look at a few examples.

Unpacking known length iterables

When the length of the data type is very obvious, you can pass in the exact number of variables as the number of values in the data type to unpack the values.

my_info = ["Lenin", "Mishra", 28, "Amsterdam"]

name, surname, age, place = my_info

# Result
>>> name
'Lenin'
>>> surname
'Mishra'
>>> age
28
>>> place
'Amsterdam'

Since I know that there are 4 values inside my list. I am passing in 4 variables to unpack those values. The values are unpacked in the same order as the provided variables.

If there is a mismatch of values and variables, Python will throw you an error.

In case when fewer variables are provided, Python will tell you that there are too many values to unpack.

Example 1

my_info = ["Lenin", "Mishra", 28, "Amsterdam"]
name, other_info = my_info

# Result
Traceback (most recent call last):
  File <input>, line 2, in <module>
    name, other_info = my_info
ValueError: too many values to unpack (expected 2)

In case when more variables are provided, Python will tell you that there are not enough values to unpack.

Example 2

my_info = ["Lenin", "Mishra", 28, "Amsterdam"]
name, surname, age, place, other = my_info

# Result
Traceback (most recent call last):
  File <input>, line 2, in <module>
    name, surname, age, place, other = my_info
ValueError: not enough values to unpack (expected 5, got 4)

Unpacking Sequence within a Sequence

Let’s look at another example. Let’s assume you provide the name and surname as a tuple (or any sequence).

my_info = [("Lenin", "Mishra"), 28, "Amsterdam"]

name, age, place = my_info

# Result
>>> name
('Lenin', 'Mishra')
>>> age
28
>>> place
'Amsterdam'

Now the name variable stores the tuple as a value with both the first name and surname as information. If we want to extract both parts of the name, we can pass in a sequence of variables.

my_info = [("Lenin", "Mishra"), 28, "Amsterdam"]

(name, surname), age, place = my_info

# Result
>>> name
'Lenin'
>>> surname
'Mishra'
>>> age
28
>>> place
'Amsterdam'

How to discard values while unpacking?

It is also possible to discard certain values that you may not need while unpacking.

Let’s say you are not interested in the place information. You can use a _ to disregard the unpacked value.

my_info = ["Lenin", "Mishra", 28, "Amsterdam"]

name, surname, age, _ = my_info

# Result
>>> name
'Lenin'
>>> surname
'Mishra'
>>> age
28

How to unpack a Python dictionary?

The process for unpacking a python dictionary is not the same as unpacking a python tuple or a list. When you apply the above method to a dictionary, you will be unpacking just the keys.

my_info = {"name":"Lenin", "age":28}

x, y = my_info

# Result
>>> x
'name'
>>> y
'age'

Now to get the values for the respective dictionary keys, you have to call the dictionary key.

>>> my_info[x]
'Lenin'
>>> my_info[y]
28

Unpacking arbitrary length iterables

Let’s be honest! It's not always possible to provide all the required variables to unpack the values. Imagine providing a million variables to unpack a list containing 1000 records! That is just sloppy.

Let’s look at an example. Suppose you have a list of university scores from the 1st to the 6th semester. While averaging, you decide to leave out the first and last score.

In this case, you need to unpack all the scores between the first and last values.

scores = [92, 90, 87, 64, 75, 91]
first, *middle, last = scores

>>> middle
[90, 87, 64, 75]

Let’s look at a log message. To learn more about Logging in Python, check out this article.

What we want to achieve is get the logging level and the logging message.

log_msg = "2019-06-05 17:43:07,889 :: __main__ :: INFO :: I am a separate Logger"
log_msg_comps = [x.strip() for x in log_msg.split('::')] 

t_stamp, file, *req_entities = log_msg_comps

>>> req_entities
['INFO', 'I am a separate Logger']

The use of star expression (*) makes unpacking very convenient for arbitrary length iterables. Imagine reading a file in Python and you want to ignore the headers. You can apply a similar technique as above.

You can also discard irrelevant values by using the _ with the star expression (*).

log_msg = "2019-06-05 17:43:07,889 :: __main__ :: INFO :: I am a separate Logger"
log_msg_comps = [x.strip() for x in log_msg.split('::')] 

# Ignore all values except the message
*_, log_message = log_msg_comps

>>> log_message
I am a separate Logger

How to skip header in a CSV in Python?

You can use the above unpacking techniques to skip the header of a CSV in Python.

Let's assume a CSV file called students.csv with the following contents.

name, weight
Lenin, 85
Sam, 65
Neha, 43
Abhi, 95

You can get rid of the header 2 ways.

Method 1

Code

import csv

with open('students.csv', 'r') as input:
    data = csv.reader(input)
    header, *rows = data
    print(header)
    print(rows)

Output

['name', ' weight']
[['Lenin', ' 85'], ['Sam', ' 65'], ['Neha', ' 43'], ['Abhi', ' 95']]

By using this approach, you store the header in a variable for use later. You don't entirely ignore it.

The rest of the rows are neatly stored in the rows variable.

Method 2

You can also completely ignore the header. For this purpose, use the _ symbol.

Code

import csv

with open('students.csv', 'r') as input:
    data = csv.reader(input)
    _, *rows = data
    print(rows)

Output

[['Lenin', ' 85'], ['Sam', ' 65'], ['Neha', ' 43'], ['Abhi', ' 95']]