Iterators & Decorators Best Practices
Guidelines for lazy iteration, decorator hygiene, and composable pipelines - the patterns that keep Python services memory-safe and debuggable.
Search across all documentation pages
Guidelines for lazy iteration, decorator hygiene, and composable pipelines - the patterns that keep Python services memory-safe and debuggable.
lambda in loops and missing @wraps.itertools for chain, islice, groupby, product. Battle-tested and lazy.groupby when grouping by key. Consecutive-key requirement is easy to forget.tee or list().try/finally or @contextmanager inside generators holding files/sockets. Consumers may stop early..close() in tests when cleanup matters. Triggers GeneratorExit at yield.yield from instead of manual for/yield loops. Clearer delegation and return propagation.islice or break conditions. count() and cycle() never stop alone.@functools.wraps on wrapper functions. Preserves __name__, docs, and annotations.def retry(n):). Avoid global mutable config in decorators.from.lru_cache). Call cache_clear when inputs change externally.maxsize on lru_cache for unbounded key spaces. Prevent memory leaks.singledispatch for open extension by type. Not long isinstance chains in one module.with for files, locks, DB transactions, and temp config. Not bare open without close path.ExitStack when number of contexts is runtime-determined. Dynamic file lists, plugin stacks.__exit__ unless deliberately suppressing. Hidden failures corrupt state.@contextmanager for simple setup/teardown under 15 lines. Class-based for reusable objects.with block.Generator when stream large or single-pass. List when need len, reuse, or indexing.
Split when each stage has name-worthy responsibility - avoid 10-line anonymous nest.
Document stacking order and metadata preservation - consumers rely on name in logs.
Cache per-function; method args include self - consider function outside class or __hash__ on immutable self.
Only when must fork single pass - memory grows with divergence.
See asyncio section - use async with for acquisition, async for for consumption.
list(pipeline(data)) in tests; assert intermediate cleanup with mocks on close.
Fine for rare folds; explicit loop often clearer for teams new to functional style.
Decorator for registration/metadata; inheritance for shared behavior implementation.
Materializing giant intermediate lists between map/filter stages - stay lazy until boundary.
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 19, 2026