List Comprehensions & Generator Expressions
Also Known As
TL;DR
Explanation
List comprehensions: [expr for item in iterable if condition] — evaluated eagerly, returns a list. Dict comprehensions: {k: v for k, v in items.items()}. Set comprehensions: {x for x in items}. Generator expressions: (expr for item in iterable) — identical syntax with parentheses, evaluated lazily, returns an iterator — no memory allocation for the full sequence. Use generators for large datasets: sum(x*x for x in range(10**9)) never builds the list. Nested comprehensions: [[cell for cell in row] for row in matrix]. PHP equivalents: array_map + array_filter for list comprehensions; PHP generators (yield) for the lazy equivalent. Python comprehensions are idiomatic and faster than equivalent for-loop constructions for pure expression transformations.
Common Misconception
Why It Matters
Common Mistakes
- Multi-line comprehensions that are harder to read than the equivalent for loop — use a loop for complex logic.
- Side effects inside comprehensions — comprehensions should be pure transformations.
- Nested comprehensions deeper than two levels — extract a named function or use loops.
- Using a list comprehension when a generator expression would avoid materialising the full list.
Code Examples
# Manual loop — verbose:
squares = []
for x in range(10):
if x % 2 == 0:
squares.append(x ** 2)
# List comprehension — idiomatic:
squares = [x ** 2 for x in range(10) if x % 2 == 0]
# Generator for one-time use:
total = sum(x ** 2 for x in range(10) if x % 2 == 0)
# List comprehension — concise, often faster than for-loop
squares = [x**2 for x in range(10)]
evens = [x for x in range(20) if x % 2 == 0]
flattened = [n for sublist in matrix for n in sublist]
# Dict comprehension:
word_count = {word: len(word) for word in ['apple', 'banana', 'cherry']}
# Set comprehension:
unique_lengths = {len(word) for word in ['apple', 'banana', 'cherry']}
# Generator expression — lazy, memory-efficient (no [])
total = sum(x**2 for x in range(1_000_000)) # doesn't build a list in memory
# When NOT to use comprehensions:
# - Complex nested logic — use a for-loop for readability
# - Side effects (e.g. printing) — for-loop is clearer
# - More than 2 conditions — extract to a function