9 Things to Know to Master List Comprehensions in Python

Originally posted on medium

This tutorial will help you learn the most common usages of list comprehensions in Python

Many more people are starting to learn Python, as it has become one of the most popular programming languages for almost anything, like web development, scientific computing, and certainly artificial intelligence.

No matter where you’re going with Python, you unavoidably have to learn Python’s data structures, variable and function declarations, conditional statements, control flows, and other basic concepts.

One important “Pythonic” feature that can be puzzling to many beginners is the list comprehension  a concise way to create lists.

Heard of it before, but don’t know what it is?

Great, this article will provide you with a head-start for mastering list comprehensions in your Python learning adventure.

For the purpose of easier organization, I’ve listed nine things that we should know about list comprehensions, including its syntax and various use cases.


1. Basic Syntax

As mentioned previously, it serves as a concise way of doing certain things, such as creating lists. The expanded form is usually expressed as a for loop, in which each item of the iterable runs certain operations as specified in the expression.

# list comprehension
[expression for item in iterable]# expanded form
for item in iterable:
    expression

2. Create a List

Suppose that we don’t know list comprehensions, we’ll probably do something like the below when it comes to the creation of a list. To do that, first, we’ll declare an empty list. Second, in the for loop, we append each item to the list.

>>> pets = ('bird', 'snake', 'dog', 'turtle', 'cat', 'hamster')
>>> uppercased_pets = []
>>> for pet in pets:
...     uppercased_pets.append(pet.upper())
... 
>>> uppercased_pets
['BIRD', 'SNAKE', 'DOG', 'TURTLE', 'CAT', 'HAMSTER']

As mentioned in the basic syntax section, we can “compress” the for loop statement into one line — using the list comprehension with just one line of code, we can conveniently create a list by iterating the original list.

>>> pets = ('bird', 'snake', 'dog', 'turtle', 'cat', 'hamster')
>>> uppercased_pets = [pet.upper() for pet in pets]
>>> uppercased_pets
['BIRD', 'SNAKE', 'DOG', 'TURTLE', 'CAT', 'HAMSTER']

3. Conditional Statement for Filtering

In this case, we need a conditional statement to filter out the items in the existing list that don’t meet certain criteria. The corresponding list comprehension has the following syntax.

# list comprehension with a conditional statement
[expression for item in iterable if some_condition]
# expanded form
for item in iterable:
    if some_condition:
        expression

Here’s an example of this usage.

>>> primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
>>> squared_primes = [x*x for x in primes if x%10 == 3]
>>> squared_primes
[9, 169, 529]

If we have a more complicated evaluation of the condition, we can even use a function.

>>> def has_four_legs(pet):
...     return pet in ('pig', 'dog', 'turtle', 'hamster', 'cat')
... 
>>> pets = ('bird', 'snake', 'dog', 'turtle', 'cat', 'hamster')
>>> four_legs_pets = [pet.capitalize() for pet in pets if has_four_legs(pet)]
>>> four_legs_pets
['Dog', 'Turtle', 'Cat', 'Hamster']

4. Conditional Assignment

Instead, we want to evaluate the condition to determine which expression is used. The syntax and its usage are given below. The syntax is also explained below.

# basic syntax
[expression0 if some_condition else expression1 for item in iterable]
# syntax explained: compared to the list comprehension's basic syntax: [expression for item in iterable], we can thin about that (expression0 if some_condition else expression1) is a whole part that constitutes the expression in the general format
>>> max_value = 10
>>> numbers = (7, 9, 11, 4, 3, 2, 12)
>>> ceiling_numbers0 = [number if number <= max_value else max_value for number in numbers] 
>>> ceiling_numbers0
[7, 9, 10, 4, 3, 2, 10]
>>> ceiling_numbers1 = [(number if number <= max_value else max_value) for number in numbers]
>>> ceiling_numbers1
[7, 9, 10, 4, 3, 2, 10]

5. Replace map()

One thing to note is that the map() function returns an iterable object, and thus we can use the list() function to generate a list from this iterable.

# map() returns an iterator object
map(function, iterable)
>>> pets = ('bird', 'snake', 'dog', 'turtle', 'cat', 'hamster')
>>> uppercased_pets = list(map(str.upper, pets))
>>> uppercased_pets
['BIRD', 'SNAKE', 'DOG', 'TURTLE', 'CAT', 'HAMSTER']

As shown previously, we can replace the map() function with the list comprehension.

>>> pets = ('bird', 'snake', 'dog', 'turtle', 'cat', 'hamster')
>>> uppercased_pets = [pet.upper() for pet in pets]
>>> uppercased_pets
['BIRD', 'SNAKE', 'DOG', 'TURTLE', 'CAT', 'HAMSTER']

6. Nested List Comprehensions

In this case, we can use the nested list comprehension, the syntax of which is also shown below.

# basic syntax of the nested list comprehensions
[expression for sublist in outer_list for item in sublist]
# expanded form
for sublist in outer_list:
    for item in sublist:
        expression
>>> nested_numbers = ((1, 4, 7, 8), (2, 3, 5))
>>> squares = [x*x for numbers in nested_numbers for x in numbers]
>>> squares
[1, 16, 49, 64, 4, 9, 25]

Although it’s technically possible to have multiple levels for the nested list comprehensions, for readability, it’s not recommended to have more than two levels.


7. Use Walrus Operator

Suppose that we want to draw ten times from a list of letters, and the list that we’re creating will only include vowels from these drawings. Here’s how we can do it using the walrus operator in the list comprehension.

Specifically, in the example below, we evaluate whether a random letter drawn from the letters is a vowel, and if it is, it’ll be assigned to the letter to which the list comprehension’s expression can have access.

>>> letters = list('this is to produce a list of letters')
>>> letters
['t', 'h', 'i', 's', ' ', 'i', 's', ' ', 't', 'o', ' ', 'p', 'r', 'o', 'd', 'u', 'c', 'e', ' ', 'a', ' ', 'l', 'i', 's', 't', ' ', 'o', 'f', ' ', 'l', 'e', 't', 't', 'e', 'r', 's']
>>> import random
>>> vowels = [letter.upper() for _ in range(0, 10) if (letter := random.choice(letters)) in list('aeoui')]
>>> vowels
['I', 'O', 'O', 'O', 'O']

8. Set Comprehension

One major difference is that we use curly braces instead of square brackets. Certainly, by design, the elements in a set won’t have duplicates as opposed to a list where duplicates are allowed.

Please note that we can also use a conditional statement in a set comprehension.

# syntax for set comprehension
{expression for item in iterable}
>>> numbers = (1, 34, 5, 8, 10, 12, 3, 90, 70, 70, 90)
>>> unique_even_numbers = {number for number in numbers if number%2 == 0}
>>> unique_even_numbers
{34, 70, 8, 10, 12, 90}

9. Dict Comprehension

# syntax for dict comprehension
{key_expression : value_expression for item in iterable}
>>> words = ('python', 'is', 'a', 'big', 'snake')
>>> len_words = {word : len(word) for word in words}
>>> len_words
{'python': 6, 'is': 2, 'a': 1, 'big': 3, 'snake': 5}
>>> len_words_p = {word : len(word) for word in words if word.startswith('p')}
>>> len_words_p
{'python': 6}

Conclusion

Beyond the list comprehension, we also talked about the set and dict comprehensions. These comprehensions allow us to create these basic collection data types very conveniently in Python with better readability.

Source: medium