python-best-practices
Skill4 starsChanged 6 months agoMITView on GitHub
Provides Python patterns for type-first development with dataclasses, discriminated unions, NewType, and Protocol. Must use when reading or writing Python files.
- Reads credentials
19 other projects use a version of this.
Adopted by
Most recently taken up by
- mahdy-gribkov/arcanatheir own version, first seen Nov 8, 2026
- The-AIOS/aiostheir own version, first seen Nov 3, 2026
- medy-gribkov/arcanatheir own version, first seen Nov 1, 2026
- jkitchin/knowhowtheir own version, first seen Nov 1, 2026
- OpenxIntelligence/Coding-Agent-Skillstheir own version, first seen Nov 1, 2026
- fullerzz/agent-skillstheir own version, first seen Oct 25, 2026
Used with
Projects with it also use react-best-practices, typescript-best-practices and 1 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
OpenAISkillreact-best-practices
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
Also in 3 projects that use this
jaydubya818Skilltypescript-best-practices
Use when TypeScript needs focused type-safety, API, or error-handling guidance.
Also in 3 projects that use this
GoogleSkilltdd
Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.
Also in 3 projects that use this
Other versions19 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 19
- The-AIOS/aios★ 105same name
- jefflester/claude-skills-supercharged★ 43same name
- baekenough/oh-my-customcode★ 42same name
- jkitchin/knowhow★ 42same name
- excatt/superclaude-plusplus★ 14same name
- I-Onlabs/claude-code-skills★ 4same name
- OpenxIntelligence/Coding-Agent-Skills★ 4same name
- Sanskar015/claude-skills-supercharged★ 3same name
- amirrezaalasti/codescribe★ 2same name
- b12consulting/skills★ 2same name
9 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository37 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- adaptSkill
- animateSkill
- arrangeSkill
- auditSkill
- bolderSkill
- clarifySkill
- code-refactorSkill
- colorizeSkill
- critiqueSkill
- delightSkill
- distillSkill
- extractSkill
- frontend-designSkill
- gitlab-integrationSkill
- git-operationsSkill
- hardenSkill
- industrial-ai-researchSkill
- latex-paper-enSkill
- latex-thesis-zhSkill
- mermaid-diagramsSkill
- normalizeSkill
- onboardSkill
- optimizeSkill
- overdriveSkill
- paper-auditSkill
- polishSkill
- pydanticSkill
- python-docsSkill
- pytorch-lightningSkill
- quieterSkill
- remotion-best-practicesSkill
- research-paper-writingSkill
- skill-creatorSkill
- teach-impeccableSkill
- typesetSkill
- typst-paperSkill
The file
We split this skill into the rules it gives an agent
9 rules. 0 are common, 4 are distinctive, and 5 are very specific to this project.
0
Common
Most of the 15 edited versions we read keep these.
4
Distinctive
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 19
Use Python's type system to prevent invalid states at type-check time.
- Very specific: line 146
Prefer smaller, focused files: one class or closely related set of functions per module.
- Very specific: line 150
Use list/dict/set comprehensions and generator expressions over explicit loops.
- Very specific: line 151
Prefer @dataclass(frozen=True) for immutable data.
- Very specific: line 152
Use functools.partial for partial application.
- Distinctive: line 153
Avoid class-level mutable state.
- Very specific: line 160
Use context managers for I/O.
- Distinctive: line 161
Add or adjust unit tests when touching logic.
- Distinctive: line 208
Use sensible defaults for development.
“Common” is measured: kept by at least 6 in 10 of the 15 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Python Best Practices
Type-First Development
Types define the contract before implementation. Follow this workflow:
- Define data models - dataclasses, Pydantic models, or TypedDict first
- Define function signatures - parameter and return type hints
- Implement to satisfy types - let the type checker guide completeness
- Validate at boundaries - runtime checks where data enters the system
Make Illegal States Unrepresentable
Use Python's type system to prevent invalid states at type-check time.
Dataclasses for structured data:
from dataclasses import dataclass
from datetime import datetime
@dataclass(frozen=True)
class User:
id: str
email: str
name: str
created_at: datetime
@dataclass(frozen=True)
class CreateUser:
email: str
name: str
# Frozen dataclasses are immutable - no accidental mutationDiscriminated unions with Literal:
from dataclasses import dataclass
from typing import Literal
@dataclass
class Idle:
status: Literal["idle"] = "idle"
@dataclass
class Loading:
status: Literal["loading"] = "loading"
@dataclass
class Success:
status: Literal["success"] = "success"
data: str
@dataclass
class Failure:
status: Literal["error"] = "error"
error: Exception
RequestState = Idle | Loading | Success | Failure
def handle_state(state: RequestState) -> None:
match state:
case Idle():
pass
case Loading():
show_spinner()
case Success(data=data):
render(data)
case Failure(error=err):
show_error(err)NewType for domain primitives:
from typing import NewType
UserId = NewType("UserId", str)
OrderId = NewType("OrderId", str)
def get_user(user_id: UserId) -> User:
# Type checker prevents passing OrderId here
...
def create_user_id(raw: str) -> UserId:
return UserId(raw)Enums for constrained values:
from enum import Enum, auto
class Role(Enum):
ADMIN = auto()
USER = auto()
GUEST = auto()
def check_permission(role: Role) -> bool:
match role:
case Role.ADMIN:
return True
case Role.USER:
return limited_check()
case Role.GUEST:
return False
# Type checker warns if case is missingProtocol for structural typing:
from typing import Protocol
class Readable(Protocol):
def read(self, n: int = -1) -> bytes: ...
def process_input(source: Readable) -> bytes:
# Accepts any object with a read() method
return source.read()TypedDict for external data shapes:
from typing import TypedDict, Required, NotRequired
class UserResponse(TypedDict):
id: Required[str]
email: Required[str]
name: Required[str]
avatar_url: NotRequired[str]
def parse_user(data: dict) -> UserResponse:
# Runtime validation needed - TypedDict is structural
return UserResponse(
id=data["id"],
email=data["email"],
name=data["name"],
)Module Structure
Prefer smaller, focused files: one class or closely related set of functions per module. Split when a file handles multiple concerns or exceeds ~300 lines. Use __init__.py to expose public API; keep implementation details in private modules (_internal.py). Colocate tests in tests/ mirroring the source structure.
Functional Patterns
- Use list/dict/set comprehensions and generator expressions over explicit loops.
- Prefer
@dataclass(frozen=True)for immutable data; avoid mutable default arguments. - Use
functools.partialfor partial application; compose small functions over large classes. - Avoid class-level mutable state; prefer pure functions that take inputs and return outputs.
Instructions
- Raise descriptive exceptions for unsupported cases; every code path returns a value or raises. This makes failures debuggable and prevents silent corruption.
- Propagate exceptions with context using
from err; catching requires re-raising or returning a meaningful result. Swallowed exceptions hide root causes. - Handle edge cases explicitly: empty inputs,
None, boundary values. Includeelseclauses in conditionals where appropriate. - Use context managers for I/O; prefer
pathliband explicit encodings. Resource leaks cause production issues. - Add or adjust unit tests when touching logic; prefer minimal repros that isolate the failure.
Examples
Explicit failure for unimplemented logic:
def build_widget(widget_type: str) -> Widget:
raise NotImplementedError(f"build_widget not implemented for type: {widget_type}")Propagate with context to preserve the original traceback:
try:
data = json.loads(raw)
except json.JSONDecodeError as err:
raise ValueError(f"invalid JSON payload: {err}") from errExhaustive match with explicit default:
def process_status(status: str) -> str:
match status:
case "active":
return "processing"
case "inactive":
return "skipped"
case _:
raise ValueError(f"unhandled status: {status}")Debug-level tracing with namespaced logger:
import logging
logger = logging.getLogger("myapp.widgets")
def create_widget(name: str) -> Widget:
logger.debug("creating widget: %s", name)
widget = Widget(name=name)
logger.debug("created widget id=%s", widget.id)
return widgetConfiguration
- Load config from environment variables at startup; validate required values before use. Missing config should fail immediately.
- Define a config dataclass or Pydantic model as single source of truth; avoid
os.getenvscattered throughout code. - Use sensible defaults for development; require explicit values for production secrets.
Examples
Typed config with dataclass:
import os
from dataclasses import dataclass
@dataclass(frozen=True)
class Config:
port: int = 3000
database_url: str = ""
api_key: str = ""
env: str = "development"
@classmethod
def from_env(cls) -> "Config":
database_url = os.environ.get("DATABASE_URL", "")
if not database_url:
raise ValueError("DATABASE_URL is required")
return cls(
port=int(os.environ.get("PORT", "3000")),
database_url=database_url,
api_key=os.environ["API_KEY"], # required, will raise if missing
env=os.environ.get("ENV", "development"),
)
config = Config.from_env()Optional: ty
For fast type checking, consider ty from Astral (creators of ruff and uv). Written in Rust, it's significantly faster than mypy or pyright.
Installation and usage:
# Run directly with uvx (no install needed)
uvx ty check
# Check specific files
uvx ty check src/main.py
# Install permanently
uv tool install tyKey features:
- Automatic virtual environment detection (via
VIRTUAL_ENVor.venv) - Project discovery from
pyproject.toml - Fast incremental checking
- Compatible with standard Python type hints
Configuration in pyproject.toml:
[tool.ty]
python-version = "3.12"When to use ty vs alternatives:
ty- fastest, good for CI and large codebases (early stage, rapidly evolving)pyright- most complete type inference, VS Code integrationmypy- mature, extensive plugin ecosystem
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

