Generators
Lazy evaluation, memory-efficient alternatives to list comprehensions
Generator Expressions
A generator expression looks almost identical to a list comprehension — the only difference is parentheses instead of square brackets:
The difference is invisible from the outside but significant on the inside.
Lazy Evaluation
A list comprehension evaluates all elements immediately and stores them in memory. A generator expression is lazy — it produces values one at a time, only when asked. Nothing is computed until you actually consume it.
Once a generator is exhausted, it is done — you cannot restart it:
Memory Efficiency
The key practical benefit: a generator never holds more than one element in memory at a time.
For one million elements, the list takes megabytes while the generator takes roughly 200 bytes — the size doesn't grow with the number of elements at all.
Passing Generators to Built-ins
The most common use in competitive programming: pass a generator directly to sum, min, max, any, all. No intermediate list needed:
Note: when a generator expression is the only argument to a function, you can drop the extra parentheses — sum(x ** 2 for x in a) instead of sum((x ** 2 for x in a)).
Filtering in Generator Expressions
Same syntax as list comprehensions:
any and all with Short-Circuit Evaluation
This is where generators really shine. any stops as soon as it finds a True, and all stops as soon as it finds a False. With a generator, the remaining elements are never computed at all:
For large ranges this can be a significant performance difference.
enumerate and zip with Generators
Generators work naturally with enumerate and zip:
When to Use a Generator vs a List
Use a generator expression when:
- You only need to iterate once
- You are passing the result directly to
sum,min,max,any,all - The sequence is very large and memory matters
- You want short-circuit behavior with
any/all
Use a list comprehension when:
- You need to index into the result (
result[i])