What Are List Comprehensions?
List comprehensions are a concise, Pythonic way to create lists from existing iterables. They compress what would normally be a multi-line for loop into a single, readable expression. Once you understand them, you'll find yourself reaching for them constantly.
The Basic Syntax
The general structure of a list comprehension is:
[expression for item in iterable if condition]
The if condition part is optional — it acts as a filter.
From Loop to Comprehension: A Side-by-Side Example
Let's say you want a list of squares for numbers 0 through 9.
Traditional loop:
squares = []
for n in range(10):
squares.append(n ** 2)
List comprehension:
squares = [n ** 2 for n in range(10)]
Both produce [0, 1, 4, 9, 16, 25, 36, 49, 64, 81], but the comprehension is cleaner and more expressive.
Adding a Filter Condition
Only want the squares of even numbers?
even_squares = [n ** 2 for n in range(10) if n % 2 == 0]
# [0, 4, 16, 36, 64]
The if clause filters items before the expression is applied. This keeps the logic tight and readable.
Working with Strings
Comprehensions shine when transforming lists of strings:
names = ["alice", "bob", "charlie", "dave"]
capitalized = [name.capitalize() for name in names]
# ["Alice", "Bob", "Charlie", "Dave"]
long_names = [name for name in names if len(name) > 4]
# ["alice", "charlie"]
Nested List Comprehensions
You can nest comprehensions to flatten 2D lists or build matrices:
# Flatten a matrix
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
Be cautious with deeply nested comprehensions — readability can suffer quickly. If your comprehension spans more than two levels of nesting, a regular loop is often clearer.
Dictionary and Set Comprehensions
The same pattern works for dictionaries and sets:
# Dictionary comprehension
word_lengths = {word: len(word) for word in ["hello", "world", "python"]}
# {"hello": 5, "world": 5, "python": 6}
# Set comprehension (removes duplicates automatically)
unique_lengths = {len(word) for word in ["hi", "hello", "hey", "world"]}
# {2, 5}
When NOT to Use List Comprehensions
List comprehensions are powerful, but they're not always the right tool:
- Complex logic: If your expression or condition requires multiple lines of logic, extract it into a function and call it in the comprehension — or just use a loop.
- Side effects: Don't use comprehensions just to run side effects (like printing). That's what
forloops are for. - Large datasets: If you're working with huge amounts of data, consider a generator expression instead — it uses
()instead of[]and doesn't load the whole list into memory at once.
# Generator expression — memory efficient
total = sum(n ** 2 for n in range(1_000_000))
Quick Reference
| Type | Syntax | Result |
|---|---|---|
| List | [expr for x in iter] | List |
| Dict | {k: v for x in iter} | Dictionary |
| Set | {expr for x in iter} | Set |
| Generator | (expr for x in iter) | Generator object |
Summary
List comprehensions are one of the features that make Python feel elegant. They encourage you to think in transformations rather than mutations, which leads to cleaner, more functional-style code. Master them, use them where they improve readability, and reach for a regular loop when the logic gets complex. That balance is the mark of a confident Python developer.