Python List Comprehensions: A Practical Guide

A guide to one of Python's most beloved features: list comprehensions. Learn how to write concise, readable code to create lists from existing iterables, complete with conditional logic.

If you want to write code that looks and feels "Pythonic," one of the first features you should master is the list comprehension. A list comprehension offers a short and readable syntax for creating a list from an existing iterable (like another list, a tuple, or a range).

It's a powerful feature that can replace clumsy for loops for list creation, making your code more elegant and often faster.

The Traditional Way: Using a for Loop

Let's say you want to create a list of the squares of the numbers from 0 to 9. The traditional way to do this would be with a for loop.

squares = []
for i in range(10):
    squares.append(i * i)

print(squares)
# Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

This code works perfectly fine, but it's a bit verbose. It takes three lines to do a very simple task.

The List Comprehension Way

A list comprehension allows you to do the exact same thing in a single, expressive line.

squares = [i * i for i in range(10)]

print(squares)
# Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

The Anatomy of a List Comprehension

A list comprehension is made up of three parts:

[expression for item in iterable]

  1. expression: The operation you want to perform on each item (e.g., i * i).
  2. for item in iterable: The loop itself, iterating over an existing iterable.

Adding Conditional Logic

List comprehensions become even more powerful when you add conditional logic.

Filtering with if

You can add an if clause at the end of the comprehension to filter items from the source iterable. Only items that satisfy the condition will be processed by the expression.

Example: Create a list of the squares of only the even numbers.

# Get the squares of even numbers from 0 to 9
even_squares = [i * i for i in range(10) if i % 2 == 0]

print(even_squares)
# Output: [0, 4, 16, 36, 64]

The structure is:

[expression for item in iterable if condition]

if-else Logic

What if you want to perform a different action based on a condition? You can use a conditional expression (ternary operator) in the expression part of the comprehension.

Example: Create a list where even numbers are squared and odd numbers are left as they are.

# Note the position of the if-else block
result = [i * i if i % 2 == 0 else i for i in range(10)]

print(result)
# Output: [0, 1, 4, 3, 16, 5, 36, 7, 64, 9]

The structure for this is different. The if-else comes before the for loop:

[expression_if_true if condition else expression_if_false for item in iterable]

Beyond Lists: Set and Dictionary Comprehensions

The same comprehension syntax can be used to create sets and dictionaries.

Set Comprehension:

Use curly braces {} to create a set, which automatically handles duplicate values.

numbers = [1, 2, 2, 3, 3, 3, 4]
squares_set = {x * x for x in numbers}

print(squares_set)
# Output: {1, 4, 9, 16}

Dictionary Comprehension:

Also use curly braces, but specify a key-value pair with a colon (:).

# Create a dictionary mapping numbers to their squares
squares_dict = {x: x * x for x in range(5)}

print(squares_dict)
# Output: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Conclusion

List comprehensions (and their set and dictionary counterparts) are a fundamental and powerful feature of Python. They allow you to write code that is:

  • Concise: They reduce the amount of code you need to write for a common task.
  • Readable: Once you are familiar with the syntax, a list comprehension is often easier to read at a glance than a multi-line for loop.
  • Efficient: They are often as fast or faster than the equivalent for loop.

For these reasons, you should prefer using comprehensions whenever you are creating a new list, set, or dictionary from an existing iterable.