Python List Comprehensions: Syntax, Filtering & Exam Traps
A concise way to create lists — and a favourite topic on Python exams. Learn the syntax, filtering, nesting, and the generator expression gotcha.
Basic syntax
A list comprehension creates a new list by applying an expression to each item in an iterable. The general form is `[expression for item in iterable]`.
squares = [x**2 for x in range(5)] print(squares) # [0, 1, 4, 9, 16] words = ['hello', 'world'] upper = [w.upper() for w in words] print(upper) # ['HELLO', 'WORLD']
Filtering with if
Add an `if` clause after the iterable to keep only items that satisfy a condition.
evens = [x for x in range(10) if x % 2 == 0] print(evens) # [0, 2, 4, 6, 8] # Combined: transform + filter even_squares = [x**2 for x in range(10) if x % 2 == 0] print(even_squares) # [0, 4, 16, 36, 64]
Nested comprehensions
You can nest comprehensions to flatten or combine iterables. Read left-to-right like nested for loops.
matrix = [[1, 2], [3, 4], [5, 6]] # Flatten a 2D list flat = [x for row in matrix for x in row] print(flat) # [1, 2, 3, 4, 5, 6] # 3×3 multiplication table table = [[r * c for c in range(1, 4)] for r in range(1, 4)]
List comprehension vs loop — performance
List comprehensions are faster than equivalent for-loops because they are optimised at the C level in CPython. But clarity matters more than speed for small lists.
# Loop — slower, more verbose
result = []
for x in range(1000):
result.append(x * 2)
# Comprehension — faster, one line
result = [x * 2 for x in range(1000)]Generator expressions — the look-alike
Replace `[]` with `()` and you get a generator expression instead of a list. Generators are lazy — they produce values one at a time and use far less memory.
# List comprehension — creates the full list immediately lst = [x**2 for x in range(1_000_000)] # ~8 MB in memory # Generator expression — produces values on demand gen = (x**2 for x in range(1_000_000)) # almost no memory print(next(gen)) # 0 print(next(gen)) # 1
Exam tip
The most common exam question is the list-vs-generator trap: `[x for x in range(5)]` returns a list, `(x for x in range(5))` returns a generator. Also watch for the filter-position gotcha — the `if` clause goes after the iterable, not after the expression.
Think you're ready? Prove it.
Take the free Python readiness test. Get a score, topic breakdown, and your exact weak areas.
Take the free Python test →Free · No sign-up · Instant results