Know if you're actually ready. Take the Python quiz → get your AI readiness report.Take the free test →

Study guide · Python

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']
NoteList comprehensions always return a new list — the original iterable is not modified.

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)]
NoteThe order is: outer loop first, inner loop second — same as nested for loops.

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
NoteExams often ask: "what is the difference between [x for x in …] and (x for x in …)?" — the answer is list vs generator (lazy evaluation).
Exam tipThe 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.

Want a person to help?

Struggling with Python? Work 1:1 with a vetted Python tutor on Wyzant. (affiliate link)

Find a Python tutor →
← All Python guides