List Comprehensions

Introduction

A list is one of the container sequences offered by Python’s standard library, as it holds the reference to the objects it contains. It is a mutable sequence.

✏️ Note: To refresh the concept of the list, click here to get a quick overview of how to make a new list.

Assuming you know the basics of the list, let us scrutinize list comprehension which is an underused but wieldy and concise method to make a list.

It consists of brackets containing an expression followed by a for clause, then zero, or more for or if clauses. The result is a new list resulting from evaluating the expression in the context of the for and if clauses that follow it.

Explanation

Testing the readability

Let’s see how list comprehensions make a program more readable and concise. Below is a program for implementing a list without using a list comprehension:

letters = 'Python'
alphabets = [] # Creating a new list
for letter in letters:
alphabets.append(letter) # Adding elements from letters to alphabets
print(alphabets)

In the code above, we create an initial blank list, alphabets, at line 2. Then, we fill it with a for loop at line 5 using letters list. Now, let’s exercise list comprehension for the same purpose and see how the program’s size decreases, and the program becomes more readable.

letters = 'Python'
alphabets = [letter for letter in letters] # Adding elements from letters to alphabets
print(alphabets)

Now, you see how a list comprehension works like a charm! We created and filled alphabets in just one line using a list comprehension, unlike the previous program (without a list comprehension) that needed three lines to do the same thing. The later program gives a sense that a Python expert wrote it.

No leaky variables in Python 3

If you’ve ever programmed in Python 2, you may have noticed that a variable leaks its value due to the surrounding scope when using a list comprehension. Run the following program to observe the issue.

letters = 'Python'
alphabets = [letters for letters in letters] # Scope of letters is surrounding scope
print(letters)

You see, when we print the letters (at line 4), instead of getting Python, we just get n of Python. This is because the scope of the first occurrence of letters in letters for letters in letters (at line 2) is the surrounding scope, which means it’s referring to the letters at line 1.

Here comes Python 3 to the rescue. It solves the problem by assigning the first occurrence of letters in letters for letters in letters with a local scope instead of the surrounding scope. Run the following program and witness the magic!

letters = 'Python'
alphabets = [letters for letters in letters] # Scope of letters is local scope
print(letters)

Python 3 saves the day by preserving the value of letters. Here, the scope of the first occurrence of letters in letters for letters in letters (at line 2) is local scope, which means it’s not pointing to the letters at line 1.

Filtering with list comprehension

We can filter values from a list using for loop or a filter method. But it requires a few lines of computation. Do you want to do it in a single line of code? If yes, then use a list comprehension.

Run the following program to see how a list comprehension can filter a list.

numbers = [1,2,3,4,5,6,7,8,9,10]
even = [number for number in numbers if number %2 ==0] # Filtering even numbers
print(even)

See how the list comprehension does wonders! It picks every number from numbers using the for keyword and filter it using an if condition, all in one single line.

Enriched iterations with list comprehension #

The list comprehension can also replace the nested for loops for the sake of efficiency. Let’s compare both of them. Below is a program for implementing enriched iterations without using a list comprehension.

even = [2,4,6,8,10]
odd = [1,3,5,7,9]
pair = []
for number1 in even: # Taking every number from even
for number2 in odd: # Taking every number from odd
pair.append((number1, number2)) # Pairing every number from even with every number from odd
print(pair)

In the code above, you can see that an outer-loop (at line 5), takes a value from even turn by turn, and an inner-loop (at line 6), takes value from odd turn by turn. The numbers are then paired in the form of a tuple in the list pair. As a result, pair holds the cartesian product of the even and odd lists.

Note: A tuple (pair) shouldn’t be generated with elements from one list!

Now, let’s use list comprehension for the same purpose, and see how the program’s size decreases, and the program becomes more readable.

even = [2,4,6,8,10]
odd = [1,3,5,7,9]
# Pairing every number from even with every number from odd
pair = [(number1,number2) for number1 in even for number2 in odd]
print(pair)

Once again, list comprehension works like a charm! We created and filled pairs in just one line (see line 5) using a list comprehension, unlike the previous program (without a list comprehension) that required four lines to do the same thing. The later program gives a sense that a Python expert wrote it.

Having some know-how about these little programming techniques makes a huge difference.