python-patterns
Python Patterns
Section titled “Python Patterns”Python development principles and decision-making for 2025. Learn to THINK, not memorize patterns.
⚠️ How to Use This Skill
Section titled “⚠️ How to Use This Skill”This skill teaches decision-making principles, not fixed code to copy.
- ASK user for framework preference when unclear
- Choose async vs sync based on CONTEXT
- Don’t default to same framework every time
1. Framework Selection (2025)
Section titled “1. Framework Selection (2025)”Decision Tree
Section titled “Decision Tree”What are you building?│├── API-first / Microservices│ └── FastAPI (async, modern, fast)│├── Full-stack web / CMS / Admin│ └── Django (batteries-included)│├── Simple / Script / Learning│ └── Flask (minimal, flexible)│├── AI/ML API serving│ └── FastAPI (Pydantic, async, uvicorn)│└── Background workers └── Celery + any frameworkComparison Principles
Section titled “Comparison Principles”| Factor | FastAPI | Django | Flask |
|---|---|---|---|
| Best for | APIs, microservices | Full-stack, CMS | Simple, learning |
| Async | Native | Django 5.0+ | Via extensions |
| Admin | Manual | Built-in | Via extensions |
| ORM | Choose your own | Django ORM | Choose your own |
| Learning curve | Low | Medium | Low |
Selection Questions to Ask:
Section titled “Selection Questions to Ask:”- Is this API-only or full-stack?
- Need admin interface?
- Team familiar with async?
- Existing infrastructure?
2. Async vs Sync Decision
Section titled “2. Async vs Sync Decision”When to Use Async
Section titled “When to Use Async”async def is better when:├── I/O-bound operations (database, HTTP, file)├── Many concurrent connections├── Real-time features├── Microservices communication└── FastAPI/Starlette/Django ASGI
def (sync) is better when:├── CPU-bound operations├── Simple scripts├── Legacy codebase├── Team unfamiliar with async└── Blocking libraries (no async version)The Golden Rule
Section titled “The Golden Rule”I/O-bound → async (waiting for external)CPU-bound → sync + multiprocessing (computing)
Don't:├── Mix sync and async carelessly├── Use sync libraries in async code└── Force async for CPU workAsync Library Selection
Section titled “Async Library Selection”| Need | Async Library |
|---|---|
| HTTP client | httpx |
| PostgreSQL | asyncpg |
| Redis | aioredis / redis-py async |
| File I/O | aiofiles |
| Database ORM | SQLAlchemy 2.0 async, Tortoise |
3. Type Hints Strategy
Section titled “3. Type Hints Strategy”When to Type
Section titled “When to Type”Always type:├── Function parameters├── Return types├── Class attributes├── Public APIs
Can skip:├── Local variables (let inference work)├── One-off scripts├── Tests (usually)Common Type Patterns
Section titled “Common Type Patterns”# These are patterns, understand them:
# Optional → might be Nonefrom typing import Optionaldef find_user(id: int) -> Optional[User]: ...
# Union → one of multiple typesdef process(data: str | dict) -> None: ...
# Generic collectionsdef get_items() -> list[Item]: ...def get_mapping() -> dict[str, int]: ...
# Callablefrom typing import Callabledef apply(fn: Callable[[int], str]) -> str: ...Pydantic for Validation
Section titled “Pydantic for Validation”When to use Pydantic:├── API request/response models├── Configuration/settings├── Data validation├── Serialization
Benefits:├── Runtime validation├── Auto-generated JSON schema├── Works with FastAPI natively└── Clear error messages4. Project Structure Principles
Section titled “4. Project Structure Principles”Structure Selection
Section titled “Structure Selection”Small project / Script:├── main.py├── utils.py└── requirements.txt
Medium API:├── app/│ ├── __init__.py│ ├── main.py│ ├── models/│ ├── routes/│ ├── services/│ └── schemas/├── tests/└── pyproject.toml
Large application:├── src/│ └── myapp/│ ├── core/│ ├── api/│ ├── services/│ ├── models/│ └── ...├── tests/└── pyproject.tomlFastAPI Structure Principles
Section titled “FastAPI Structure Principles”Organize by feature or layer:
By layer:├── routes/ (API endpoints)├── services/ (business logic)├── models/ (database models)├── schemas/ (Pydantic models)└── dependencies/ (shared deps)
By feature:├── users/│ ├── routes.py│ ├── service.py│ └── schemas.py└── products/ └── ...5. Django Principles (2025)
Section titled “5. Django Principles (2025)”Django Async (Django 5.0+)
Section titled “Django Async (Django 5.0+)”Django supports async:├── Async views├── Async middleware├── Async ORM (limited)└── ASGI deployment
When to use async in Django:├── External API calls├── WebSocket (Channels)├── High-concurrency views└── Background task triggeringDjango Best Practices
Section titled “Django Best Practices”Model design:├── Fat models, thin views├── Use managers for common queries├── Abstract base classes for shared fields
Views:├── Class-based for complex CRUD├── Function-based for simple endpoints├── Use viewsets with DRF
Queries:├── select_related() for FKs├── prefetch_related() for M2M├── Avoid N+1 queries└── Use .only() for specific fields6. FastAPI Principles
Section titled “6. FastAPI Principles”async def vs def in FastAPI
Section titled “async def vs def in FastAPI”Use async def when:├── Using async database drivers├── Making async HTTP calls├── I/O-bound operations└── Want to handle concurrency
Use def when:├── Blocking operations├── Sync database drivers├── CPU-bound work└── FastAPI runs in threadpool automaticallyDependency Injection
Section titled “Dependency Injection”Use dependencies for:├── Database sessions├── Current user / Auth├── Configuration├── Shared resources
Benefits:├── Testability (mock dependencies)├── Clean separation├── Automatic cleanup (yield)Pydantic v2 Integration
Section titled “Pydantic v2 Integration”# FastAPI + Pydantic are tightly integrated:
# Request validation@app.post("/users")async def create(user: UserCreate) -> UserResponse: # user is already validated ...
# Response serialization# Return type becomes response schema7. Background Tasks
Section titled “7. Background Tasks”Selection Guide
Section titled “Selection Guide”| Solution | Best For |
|---|---|
| BackgroundTasks | Simple, in-process tasks |
| Celery | Distributed, complex workflows |
| ARQ | Async, Redis-based |
| RQ | Simple Redis queue |
| Dramatiq | Actor-based, simpler than Celery |
When to Use Each
Section titled “When to Use Each”FastAPI BackgroundTasks:├── Quick operations├── No persistence needed├── Fire-and-forget└── Same process
Celery/ARQ:├── Long-running tasks├── Need retry logic├── Distributed workers├── Persistent queue└── Complex workflows8. Error Handling Principles
Section titled “8. Error Handling Principles”Exception Strategy
Section titled “Exception Strategy”In FastAPI:├── Create custom exception classes├── Register exception handlers├── Return consistent error format└── Log without exposing internals
Pattern:├── Raise domain exceptions in services├── Catch and transform in handlers└── Client gets clean error responseError Response Philosophy
Section titled “Error Response Philosophy”Include:├── Error code (programmatic)├── Message (human readable)├── Details (field-level when applicable)└── NOT stack traces (security)9. Testing Principles
Section titled “9. Testing Principles”Testing Strategy
Section titled “Testing Strategy”| Type | Purpose | Tools |
|---|---|---|
| Unit | Business logic | pytest |
| Integration | API endpoints | pytest + httpx/TestClient |
| E2E | Full workflows | pytest + DB |
Async Testing
Section titled “Async Testing”# Use pytest-asyncio for async tests
import pytestfrom httpx import AsyncClient
@pytest.mark.asyncioasync def test_endpoint(): async with AsyncClient(app=app, base_url="http://test") as client: response = await client.get("/users") assert response.status_code == 200Fixtures Strategy
Section titled “Fixtures Strategy”Common fixtures:├── db_session → Database connection├── client → Test client├── authenticated_user → User with token└── sample_data → Test data setup10. Decision Checklist
Section titled “10. Decision Checklist”Before implementing:
- Asked user about framework preference?
- Chosen framework for THIS context? (not just default)
- Decided async vs sync?
- Planned type hint strategy?
- Defined project structure?
- Planned error handling?
- Considered background tasks?
11. Anti-Patterns to Avoid
Section titled “11. Anti-Patterns to Avoid”❌ DON’T:
Section titled “❌ DON’T:”- Default to Django for simple APIs (FastAPI may be better)
- Use sync libraries in async code
- Skip type hints for public APIs
- Put business logic in routes/views
- Ignore N+1 queries
- Mix async and sync carelessly
- Choose framework based on context
- Ask about async requirements
- Use Pydantic for validation
- Separate concerns (routes → services → repos)
- Test critical paths
Remember: Python patterns are about decision-making for YOUR specific context. Don’t copy code—think about what serves your application best.
Gap Analysis Rule
Section titled “Gap Analysis Rule”Always identify gaps and suggest next steps to users. In case there is no gaps anymore, then AI should clearly state that there is no gap left.