Are list comprehensions faster than equivalent for-loops in Python, and when should you prefer a generator expression instead?
List comprehensions are typically 20–50% faster than equivalent for-loops with list.append() because the bytecode is optimised and the attribute lookup for append is avoided. Generator expressions use O(1) memory versus O(n) for a comprehension, so prefer them when you only iterate once.
How to think about it
What the interviewer is really probing
This is a two-part question: do you understand why comprehensions are faster, and do you know the memory trade-off that makes generator expressions the right choice sometimes? Both parts matter equally.
Why comprehensions are faster
Every iteration of a plain for loop that calls result.append(x) has to look up the append attribute on the list object — that’s a Python-level attribute lookup on each pass. A list comprehension uses a dedicated LIST_APPEND bytecode instruction that skips that lookup entirely and runs at the C level.
# Plain loop — attribute lookup each iteration
result = []
for x in range(100_000):
result.append(x * x)
# List comprehension — faster, more idiomatic
result = [x * x for x in range(100_000)]
# With a condition
evens = [x for x in range(100_000) if x % 2 == 0]
All three produce a fully materialised list in memory — O(n) space.
Generator expression — O(1) space
A generator expression looks identical to a list comprehension but uses parentheses instead of brackets. It produces values on demand rather than building a list upfront:
# No list is built; values are produced one at a time
total = sum(x * x for x in range(100_000))
# Pass a genexp to any function that accepts an iterable
max_val = max(x * x for x in data)
Interactive benchmark — measure it yourself
When to choose which
Use a list comprehension when:
- You need random access (
result[i]),len(), or multiple passes. - You need to pass the collection to something that requires a concrete sequence.
Use a generator expression when:
- You only iterate once — e.g. passing to
sum(),any(),max(). - The dataset is large enough that materialising it would stress RAM.