Iterators and Context Managers
Understand Python’s iteration protocol, build lazy generators, and encapsulate setup and cleanup with context managers for reliable resource handling.
Before this lesson
Distinguish iterable from iterator
Build a lazy generator function
Implement resource-safe context management
The short answer
An iterable can produce an iterator; an iterator yields values until StopIteration. Generator functions implement that protocol with yield. Context managers pair acquisition and cleanup around a with block, including exceptional exits.
Build the mental model
iter asks an iterable for an iterator, and next requests one value. A generator function suspends local state at yield and resumes on the next request. This supports streaming data that may be large or unbounded.
The central idea in this lesson is language protocols. Read the rule, predict a concrete outcome, and then run the smallest example that can confirm or reject the prediction. This separates knowledge from familiarity with syntax.
Make the design choice explicit
A context manager implements enter and exit, or can be created with contextlib.contextmanager. It is useful for locks, temporary configuration, database transactions, and other resources whose cleanup must not depend on every caller remembering it.
from contextlib import contextmanager
@contextmanager
def managed_label(name):
print(f"open {name}")
try:
yield name.upper()
finally:
print(f"close {name}")
with managed_label("report") as label:
print(label)Expected output
open report REPORT close report
Trace the example before running it. Identify each input, transformation, returned value, and side effect. Then change one boundary value and explain why the new behavior follows from the rule rather than memorizing the output.
Recognize failure modes
Iterators are stateful and normally exhaust once. Converting one to a list consumes it. Generator cleanup may be delayed if the consumer abandons it, so critical external resources should be owned by an explicit with block.
Use a professional practice loop
Turn the concept into a repeatable workflow: write down the expected behavior, implement one coherent change, run a representative example, and retain a regression check. If the result surprises you, capture the exact input and error before changing anything.
Review the program for names, boundaries, and hidden side effects. A solution is complete when another developer can understand its contract, reproduce its setup, and verify both the successful path and one meaningful failure path.
Quick knowledge check
Answer before you reveal.
01What makes a generator lazy?
Its body advances only when the consumer requests another value, preserving suspended state between requests.
02What four steps make the practice loop reliable?
Predict the behavior, make one coherent change, run it, and retain a check that detects regression.
Exercise
Practice challenge
Write a generator that streams valid integers from text lines and a context manager that measures and reports how long consumption takes.
Requirements
- The successful path produces the documented result
- At least one boundary or invalid case is handled deliberately
- Calculation or domain logic is separated from console interaction
Optional extension: Add one automated regression check for the most important rule.
Open in Python compilerLesson checkpoint
One small step locks it in
Mark this lesson complete, then keep the momentum going.
Clear up the details
Frequently asked questions
Is language protocols only important in large programs?
No. Small programs reveal the same rules with less noise, and learning the rule early prevents fragile habits from becoming architecture.
Should I memorize every API used here?
No. Memorize the mental model and how to verify behavior. Use documentation for exact names and parameters when needed.
How do I know the exercise is finished?
Meet every success criterion, test at least one boundary or failure case, and explain why the output follows from the code.