writing-python
Python Development (3.14+)
Core Philosophy
-
Stdlib and Mature Libraries First
- Always prefer Python stdlib solutions
- External deps only when stdlib insufficient
- Prefer dataclasses over attrs, pathlib over os.path
-
Type Hints Everywhere (No Any)
- Python 3.14 has lazy annotations by default
- Use Protocol for structural typing (duck typing)
- Avoid Any—use concrete types or generics
-
Protocol Over ABC
- Protocol for implicit interface satisfaction
- ABC only when runtime isinstance() needed
- Protocols are more flexible and Pythonic
-
Flat Control Flow
- Guard clauses with early returns
- Pattern matching to flatten conditionals
- Maximum 2 levels of nesting
-
Explicit Error Handling
- Custom exception hierarchy for domain errors
- Raise early, handle at boundaries
- except ValueError, TypeError: (no parens needed in 3.14+)
Quick Patterns
Protocol-Based Dependency Injection
from typing import Protocol
# Protocol at consumer (like Go interfaces)
class UserStore(Protocol):
def get(self, id: str) -> User | None: ...
def save(self, user: User) -> None: ...
class UserService:
def __init__(self, store: UserStore):
self.store = store # accepts any matching impl
Flat Control Flow (No Nesting)
# GOOD: guard clauses, early returns
def process(user: User | None) -> Result:
if user is None:
raise ValueError("user required")
if not user.email:
raise ValueError("email required")
if not is_valid_email(user.email):
raise ValueError("invalid email")
return do_work(user) # happy path at end
# BAD: nested conditions
def process(user: User | None) -> Result:
if user is not None:
if user.email:
if is_valid_email(user.email):
return do_work(user)
raise ValueError("invalid")
Pattern Matching
# Flatten complex conditionals with match
match event:
case {"type": "click", "x": x, "y": y}:
handle_click(x, y)
case {"type": "key", "code": code}:
handle_key(code)
case _:
raise ValueError(f"Unknown event: {event}")
Type Hints (No Any)
# GOOD: concrete types
def process_users(users: list[User], limit: int | None = None) -> list[Result]:
...
# GOOD: generics when needed
from typing import TypeVar
T = TypeVar("T")
def first(items: list[T]) -> T | None:
return items[0] if items else None
# BAD: unnecessary Any
def process(data: Any) -> Any: # Don't do this
...
Error Handling
# except without parens (PEP 758, Python 3.14+)
except ValueError, TypeError:
handle_error()
# Custom exceptions
class NotFoundError(AppError):
def __init__(self, resource: str, id: str):
self.resource = resource
self.id = id
super().__init__(f"{resource} not found: {id}")
Python 3.14 Features
- Deferred annotations: No
from __future__ import annotations - Template strings (t""):
t"Hello {name}"returns Template - except without parens:
except ValueError, TypeError:(PEP 758) - concurrent.interpreters: True parallelism
- compression.zstd: Zstandard in stdlib
- Free-threaded build: No GIL (opt-in)
References
- PATTERNS.md - Code patterns and style
- CLI.md - CLI application patterns
- TESTING.md - Testing with pytest
Tooling
uv sync # Install deps from pyproject.toml
uv add pkg # Add dependency
uv run python script.py # Run script in project env
uv run --with pkg python script.py # Run with one-off dep (no install)
uv run --extra test pytest -v # Run tests (optional-dep group)
ruff check --fix . # Lint and autofix
ruff format . # Format
mypy . # Type check
More from alexei-led/claude-code-config
brainstorming-ideas
Turn ideas into designs through collaborative dialogue. Use when user wants to brainstorm, design features, explore approaches, or think through implementation before coding.
19refactoring-code
Batch refactoring via MorphLLM edit_file. Use for "refactor across files", "batch rename", "update pattern everywhere", large files (500+ lines), or 5+ edits in same file.
11testing-e2e
E2E testing with Playwright MCP for browser automation, test generation, and UI testing. Use when discussing E2E tests, Playwright, browser testing, UI automation, visual testing, or accessibility testing. Supports TypeScript tests and Go/HTMX web applications.
10looking-up-docs
Library documentation via Context7. Use for API references, code examples, framework docs.
7writing-typescript
Idiomatic TypeScript development. Use when writing TypeScript code, Node.js services, React apps, or discussing TS patterns. Emphasizes strict typing, composition, and modern tooling (bun/vite).
7fixing-code
Fix ALL issues via parallel agents with zero tolerance quality enforcement. Use when user says "fix", "fix issues", "fix errors", "fix all", "fix bugs", "fix lint", "fix tests", or wants to resolve code problems.
6