Lab: idioms capstone
Apply comprehensions, generators, decorators, classes, context managers, and type hints in one connected session.
- Write generators for memory-efficient data pipelines
- Create a decorator that adds behaviour without touching the original function
- Annotate function signatures and dataclasses with type hints
- Use context managers for resource handling
Optional capstone lab. This session ties together the intermediate Python module: comprehensions, generators, decorators, classes and dataclasses, context managers, and type hints. Three checkpoints.
Warm-up — comprehension vs generator
Run both. Notice that the generator version never builds the full list in memory — it produces one value at a time:
Checkpoint 1 — infinite counter generator
Write counter(start=0, step=1) — a generator that yields values starting at
start, incrementing by step, forever. Callers stop it with itertools.islice
or by breaking out of the loop.
Write counter(start=0, step=1) — a generator that yields start, start+step, start+2*step, ... indefinitely.
list(itertools.islice(counter(0, 2), 5)) → [0, 2, 4, 6, 8]Checkpoint 2 — timing decorator
Write timed — a decorator that wraps any function and prints how long it took
to run (in milliseconds, rounded to 1 decimal place) after each call, like:
"slow_fn took 123.4 ms". The wrapper must return the original return value.
Write timed — a decorator that prints '<function_name> took X.X ms' after each call and returns the original return value. Use time.perf_counter() for timing.
@timed
def greet(): return "hi" → prints "greet took 0.0 ms" and returns "hi"Checkpoint 3 — typed dataclass
Run this and then extend it: add a full_name property that returns
f"{first} {last}", and annotate age as int (it's currently Any).
Type hints in dataclasses are enforced by type checkers (mypy, pyright) but not
by Python at runtime — Person('a', 'b', 'not-an-int') won't raise. The value
is in editor feedback and mypy catches, not runtime guards.
Done?
Three green checks means you're writing idiomatic intermediate Python: lazy generators for pipelines, decorators to add cross-cutting behaviour, and dataclasses with proper type annotations. These are the patterns you'll see in every serious Python codebase.