Python Best Practices
This skill applies modern Python mechanisms without adding annotation or packaging ceremony. It favors inference, precise structural contracts, explicit runtime validation, side-effect-free imports, and context-managed resource ownership.
Effective Strategies for Python
Read the linked guidance that governs the current task before writing or reviewing Python.
- Make type contracts precise without annotation ceremony.
- Let the checker infer obvious implementation results; add annotations only when inference cannot express the contract.
- Depend on the smallest required behavior with protocols, not a vendor's concrete client.
- In Python 3.13+, express caller-relevant relationships with PEP 695 generics, avoiding module-level
TypeVardeclarations and needless generics. - Make a new finite-state member a type-checking failure with exhaustive handling.
- Narrow optional values before use so the owning layer—not a cast or fabricated fallback—decides whether absence is preserved or rejected.
- Validate untrusted data and make invalid states explicit.
- Parse serialized input once at the controlled boundary so untrusted mappings do not spread inward.
- Do not turn missing required data into a plausible value; preserve absence or fail at the owning boundary.
- Keep required runtime checks active under optimization; do not use assertions for validation.
- Catch only expected exceptions at the operation that raises them through narrow exception handling.
- Keep packages explicit, inert, and independently distributable.
- Keep imports inert and consumer-facing names deliberate with explicit public exports.
- Prevent checkout-dependent imports by following the Python naming and
srclayout. - Publish intentional inline types with
py.typed, reserving third-party stubs for dependencies that lack complete inline types instead of adding markers merely to silence diagnostics. - Give every independently buildable distribution its own declared metadata and direct dependencies.
- Make packaging errors visible by not mutating import paths.
- Keep asynchronous resource and traversal ownership visible.
- Make async cleanup inseparable from acquisition with async context managers.
- Preserve page boundaries and consumer control over remote traversal through async pagination.