Generators
- Write generator functions with
yield - Save memory by iterating lazily instead of building lists
- Chain generators for data-pipeline patterns
- Convert generators to lists when needed
Generators power itertools, asyncio's original coroutine model, Django QuerySet iteration, and every streaming ETL job. They're the reason you can process a 50GB log file on a laptop — and a common interview probe for memory awareness.
- Iterating a generator twice — it's exhausted after the first pass; wrap in
list()or rebuild if you need reuse. - Confusing
yieldwithreturn—returnin a generator raisesStopIterationwith the value, not a plain result. - Building a generator when you need
len()or indexing — you'll getTypeError; use a list oritertools.tee.
A generator function uses yield. Each yield pauses the function and hands a value to the caller. The next iteration resumes right where it left off.
Why it matters
- Memory: process a billion items without holding them all
- Composition: pipelines of
yieldare tiny and readable
Generator expression
(expr for x in seq) — like a list comprehension but lazy.
Try it
- Write a generator that yields the first
nsquare numbers. - Use a generator expression with
max(...)to find the longest word in a list.
3 graded exercises
Write the code, click Check. We’ll tell you exactly what to fix.
- Exercise 1
Write a generator function
first_squares(n)that yields the squares of1..ninclusive. Then printlist(first_squares(5))— expected:[1, 4, 9, 16, 25]. - Exercise 2
Use a generator expression (parens, not brackets) with
sum(...)to compute the sum of squares of1..100. Print just that total. Expected:338350. - Exercise 3
Write a generator
take_while(pred, seq)that yields items fromsequntilpred(x)first returns False (then stops). Test withlist(take_while(lambda n: n < 5, [1, 2, 4, 5, 3]))— expected:[1, 2, 4](stops at 5, never yields the3).