Pythonic Patterns Best Practices
Rules for readable, maintainable Python structure - from EAFP to dependency wiring.
Search across all documentation pages
Rules for readable, maintainable Python structure - from EAFP to dependency wiring.
with for acquire/release pairs. Files, locks, and transactions need guaranteed teardown.thing_from_env / build_thing. Callers recognize composition-root helpers.get_db() singletons in service methods.None sentinel plus fresh container inside the function.None is valid data. Document is checks for UNSET objects.build(), not in setters. Keep partial builder state internal.except. Log context; re-raise unless suppression is contractual.True/False params.**kwargs. TypedDict or Pydantic at HTTP/CLI boundaries.StrEnum or Literal for static checking.Constructor injection plus protocols - tests improve immediately without frameworks.
One-off scripts under ~100 lines: plain functions, no bus, no builder.
Central registry module, typed keys as StrEnum, and tests that fail on unknown keys.
No. @contextmanager covers most cases; classes when enter/exit state is substantial.
Explicit, readable, flat - these practices operationalize the Zen of Python in architecture.
Only for boundaries other modules subscribe to. Internal steps stay direct calls.
Introduce dict mapping existing branches; keep elif delegating until coverage matches; delete branches.
Depends() is parameter injection at routes - same principle, framework-managed scope per request.
ruff B006 (mutable defaults), E722 (bare except), and pyright on protocol implementations.
Start with Pythonic Patterns Basics, then review one anti-pattern per sprint.
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