Python List Comprehension

Introduction

The Python list comprehension is a concise and powerful way to create lists. It allows you to generate new lists by applying an expression to each item in an existing iterable (such as a list, tuple, set, or string) and filtering the items based on specified conditions. It is useful in generating sequences, data cleaning, and data transformation.

In many cases, list comprehensions are more efficient than traditional for loops because they are optimized internally by Python’s interpreter. This can result in faster execution times for many operations.

Basic Python List Comprehension Syntax

The basic syntax of a list comprehension consists of square brackets [] that surround an expression followed by for loop-like syntax.

Here’s the general structure of a Python list comprehension:

[expression for item in iterable]
  • expression: An expression is some syntax that produces a value. It’s typically some function or calculation in terms of the item variable.
  • item: A variable that represents each item in the iterable.
  • iterable: The original iterable being operated on, from which elements will be processed. This can be any object type that implements the iterable protocol.

Creating a Simple List With a List Comprehension

Let’s start with a simple example. Suppose you want to create a list of the squares of numbers from 1 to 5. You can achieve this using a list comprehension.

Example:

squares = [x**2 for x in range(1, 6)]
print(squares)

Output:

[1, 4, 9, 16, 25]

In this example:

  • x**2: The expression that calculates the square of each number.
  • range(1, 6): An iterable that generates the numbers 1 to 5.
  • for x in range(1, 6): Iterates through numbers from 1 to 5.

The resulting squares list contains [1, 4, 9, 16, 25].

Using if Clauses in List Comprehensions

List comprehensions can also include an optional if clause to filter elements from the original iterable based on a condition.

Here’s the syntax for using an if clause:

[expression for item in iterable if condition]
  • condition: A boolean expression that determines whether an item should be included in the new list.

Let’s see an example where we use an if clause to filter even numbers from a list.

Example:

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = [x for x in numbers if x % 2 == 0]
print(even_numbers)

Output:

[2, 4, 6, 8, 10]

In this example, the if x % 2 == 0 condition checks whether a number is even using the reminder upon division operator %. Only the even numbers from the numbers list are included in the even_numbers list. The result is [2, 4, 6, 8, 10].

Using if-else Ternary Expressions

A ternary expression has a condition and assumes a different value depending on whether the condition is true or false. It’s called a ternary expression because it has three elements: the condition, an expression for when it’s true, and an expression for when it’s false.

The ternary expression is general syntax that fits within any expression context in Python, but it works very well in conjunction with list comprehensions to conditionally modify elements.

The syntax for a ternary expression within a list comprehension is:

[expression_if_true if condition else expression_if_false for item in iterable]
  • condition: Determines which expression will be evaluated.
  • expression_if_true: Evaluated if the condition is true.
  • expression_if_true: Evaluated if the condition is false.

The following example uses a ternary expression to create a list of “even” or “odd” strings based on the number

Example:

numbers = [1, 2, 3, 4, 5]
even_odd_labels = ["even" if x % 2 == 0 else "odd" for x in numbers]
print(even_odd_labels)

Output:

['odd', 'even', 'odd', 'even', 'odd']

Nested List Comprehensions

Python also supports nested list comprehensions, allowing you to create lists from more complex, nested data structures. With nested list comprehensions, you can generate lists from iterables of iterables, such as lists of tuples.

The basic syntax of a nested list comprehension is as follows:

[expression for inner_iterable in outer_iterable for item in inner_iterable]
  • expression: The expression that will be applied to each item.
  • inner_iterable: The variable that receives the inner iterables. For example, if you are processing a list of tuples, this variable will receive the individual tuples.
  • outer_iterable: This is the outer, overall iterable. If you are processing a list of tuples, this is the overall list itself.

The following example flattens a 2-dimensional list (a.k.a. a list of lists or a matrix) using a nested list comprehensions.

Example:

matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
flattened = [x for row in matrix for x in row]
print(flattened)

Output:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

In the example above, matrix is a list of lists. The nested comprehension iterates through each row in the matrix and then through each item in those rows.

Note that in the previous example and some other examples, the expression x is the same as the item, x, but it certainly doesn’t have to be this way, as the first example in this lesson, which squares numbers in a list, shows.

It is also possible to process multiple levels of nesting by chaining more forin clauses in the comprehension going from the outermost level on the left to innermost on the right.

The following example demonstrates this by flattening a 3-dimensional.

Example:

matrix = [[[1, 2], [3, 4]], [[5, 6], [7, 8]], [[9, 10], [11, 12]]]
flattened = [x for row in matrix for col in row for x in col]
print(flattened)

Output:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

As with the non-nested list comprehensions, it is also possible to add if clauses to every level of nesting.

The following is the general syntax for nested list comprehensions with if clauses included:

[expression for inner_iterable in outer_iterable if outer_condition for item in inner_iterable if inner_condition]

The next example uses a nested list comprehension with if clauses on both levels to pick even numbers from sub-lists that are even in length.

Example:

matrix = [[1, 2], [3, 4, 5], [6, 7, 8, 9], [10, 11, 12]]
new_list = [x for row in matrix if len(row) % 2 == 0 for x in row if x % 2 == 0]
print(new_list)

Output:

[2, 6, 8]

As you can see, nested list comprehensions, especially those with conditions, can become difficult to understand, and therefore you should use them judiciously.

Half of the advantage of list comprehensions is conciseness, clarity, and ease of use. The other half is performance gain. If a complicated list comprehension is not helping you with the former, consider using it only if the gain in performance is really necessary and worth trouble. The alternative to list comprehensions is creating a list using for loops.

Summary & Reference for Python List Comprehension

List comprehensions are a powerful and concise way to create new lists by applying expressions to items in existing iterables.


The basic list comprehension syntax has square brackets [] that surround an expression followed by for loop-like syntax.

[expression for item in iterable]

Here is an example that generates a list of squares:

squares = [x**2 for x in range(1, 6)]  # squares --> [1, 4, 9, 16, 25]

List comprehensions can include if clauses for filtering elements based on conditions.

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = [x for x in numbers if x % 2 == 0]  # even_numbers --> [2, 4, 6, 8, 10]

Ternary expressions within list comprehensions allow for conditional element modification.

numbers = [1, 2, 3, 4, 5]
even_odd_labels = ["even" if x % 2 == 0 else "odd" for x in numbers]   # even_odd_labels --> ['odd', 'even', 'odd', 'even', 'odd'] 

Python supports nested list comprehensions for creating lists from nested iterables of iterables structures.

matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
flattened = [x for row in matrix for x in row]  # flattened --> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

You can nest comprehensions with multiple levels and include if clauses at each level.

matrix = [[1, 2], [3, 4, 5], [6, 7, 8, 9], [10, 11, 12]]
new_list = [x for row in matrix if len(row) % 2 == 0 for x in row if x % 2 == 0]  # new_list --> [2, 6, 8]

While list comprehensions provide concise and efficient solutions, it’s important to strike a balance between complexity and readability. In cases where list comprehension readability is compromised, consider using traditional for loops as an alternative.