Python Mastery · Chapter 8 · ~20 min · Intermediate
Generators & Iterators: Streaming Big Data
How do you process a 50 GB log file on a computer with only 8 GB of RAM? Meet Python generators: lazy evaluation, yield, and zero-memory streaming pipelines.
- Know why lazy beats eager for big data
- Understand yield as a pause button
- Build streaming generator pipelines
- Use iter() and next() confidently
1The RAM Crisis: Eager Lists vs. Lazy Streams
Standard Python collections (lists, dicts, sets) are eager: every single item must be computed and stored in physical RAM at once. If you load 10 million rows from a database into a list, your program will crash with MemoryError.
A generator is lazy: it calculates each value on demand, hands it to you, and immediately discards it before generating the next one.
Notice how the list grows with dataset size (O(N)), while the generator stays at a flat ~112 bytes (O(1)).
Allocates all elements in RAM before executing the next line of code.
Zero elements stored! Only remembers formula and pointer to current step.
2The Conveyor Belt: yield vs return
A normal function has a return statement: it gives you an answer, destroys its stack frame, and forgets all its local variables.
A function with yield is a generator factory. When called, it doesn't run the code immediately. Instead, each call to next() runs until it hits yield, pauses, and freezes its state.
yield vs returnWatch the function pause mid-execution and remember its exact line number.
Mental model
yield is a pause button on a cassette tape
return ejects the tape — the function is finished and its local variables are gone. yield presses pause: it hands out one value and remembers exactly where it stopped. Calling next() presses play again.
What happens to a generator's local variables after yield?
3Generator Expressions: () vs []
Just like list comprehensions, Python gives you generator expressions. The only difference is swapping square brackets for parentheses:
Builds the entire list in RAM immediately.
Creates a lightweight generator object that yields values one at a time.
Unlike a list, once a generator yields all its items, it is empty forever. Looping over it again yields nothing!
gen = (x ** 2 for x in [1, 2, 3])
# Pass 1:
for n in gen:
print(n) # 1, 4, 9
# Pass 2:
for n in gen:
print(n) # NOTHING! Generator is exhausted!Which uses almost no memory for a billion numbers?
4Building Streaming Big Data Pipelines
The true superpower of generators is pipeline chaining. You can connect multiple generator functions like Unix pipes (cat | grep | cut), processing gigabytes of data in a continuous stream without storing intermediate arrays.
read_lines() ➔ filter_errors() ➔ emit_alerts()
5The Iterator Protocol: iter() and next()
Ever wonder how for item in items: actually works in Python? Behind the scenes, it executes this two-step protocol:
# What Python does behind every for-loop:
iterator = iter(collection) # Calls __iter__()
while True:
try:
item = next(iterator) # Calls __next__()
print(item)
except StopIteration: # Loop finishes cleanly!
break6Challenge: Streaming Architect
Test your mastery of lazy evaluation, yield, generator expressions, and memory optimization. Score 5/5 to complete Chapter 8!
Generators & Iterators: Streaming Big Data · code lab
Edit the example, run it with Python, or step through the lines.
1def squares(limit):2 for number in range(limit):3 yield number * number45for value in squares(4):6 print(value)
Names
Objects in memory
Python output
Run the code to see its output.
1.What does the 'yield' keyword do inside a function?
2.How much memory does a generator expression (x for x in range(10_000_000)) take in Python?
3.What exception is raised when a generator runs out of items?
4.What happens if you loop over the exact same generator object twice?
5.How do you distinguish a list comprehension from a generator expression syntactically?
Run and benchmark the 10,000-sensor streaming generator in the Python Playground (code preloaded).
7Recap
- Eager vs Lazy: Lists store all data in RAM; generators compute items on the fly (O(1) memory).
- yield: Pauses execution, emits a value, and remembers the local frame for the next call.
- Generator Expressions: Use
(x for x in data)instead of[x for x in data]for zero-overhead loops. - Single-Use Exhaustion: A generator can only be iterated over once.
- Pipeline Architecture: Chain generator stages to process endless streams and huge files cleanly.
Finish the challenge above to complete the chapter, or