Agent skill
python-best-practices
Python development best practices, patterns, and conventions. Use when writing Python code, reviewing .py files, discussing pytest, asyncio, type hints, pydantic, dataclasses, or Python project structure. Triggers on mentions of Python, pytest, mypy, ruff, black, FastAPI, Django, Flask.
Install this agent skill to your Project
npx add-skill https://github.com/eous/dotclaude/tree/main/skills/python-best-practices
SKILL.md
Python Best Practices Skill
This skill provides guidance on Python development best practices, patterns, and conventions.
Code Style
Naming Conventions
- Variables/Functions:
snake_case - Classes:
PascalCase - Constants:
UPPER_SNAKE_CASE - Private:
_single_leading_underscore - "Dunder":
__double_underscore__(reserved for Python)
Formatting
- 4 spaces for indentation (never tabs)
- Max line length: 88-120 characters (project dependent)
- Use Black or Ruff for auto-formatting
- Blank lines: 2 between top-level definitions, 1 within classes
Type Hints
# Function signatures
def process_data(items: list[str], limit: int = 10) -> dict[str, int]:
...
# Optional values
def find_user(user_id: int) -> User | None:
...
# Complex types
from typing import TypeVar, Generic, Protocol
T = TypeVar('T')
class Repository(Protocol[T]):
def get(self, id: int) -> T | None: ...
def save(self, entity: T) -> None: ...
Error Handling
# DO: Specific exceptions
try:
user = get_user(user_id)
except UserNotFoundError:
logger.warning(f"User {user_id} not found")
return None
# DON'T: Bare except
try:
user = get_user(user_id)
except: # Bad - catches everything including KeyboardInterrupt
pass
# Custom exceptions
class DomainError(Exception):
"""Base class for domain exceptions."""
pass
class UserNotFoundError(DomainError):
def __init__(self, user_id: int):
self.user_id = user_id
super().__init__(f"User {user_id} not found")
Data Classes and Models
from dataclasses import dataclass, field
from datetime import datetime
@dataclass
class User:
id: int
name: str
email: str
created_at: datetime = field(default_factory=datetime.now)
tags: list[str] = field(default_factory=list)
def __post_init__(self):
self.email = self.email.lower()
# For validation, use Pydantic
from pydantic import BaseModel, EmailStr, Field
class UserCreate(BaseModel):
name: str = Field(min_length=1, max_length=100)
email: EmailStr
model_config = {"str_strip_whitespace": True}
Async Patterns
import asyncio
from typing import AsyncIterator
# Async context manager
class AsyncDatabaseConnection:
async def __aenter__(self) -> "AsyncDatabaseConnection":
await self.connect()
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
await self.close()
# Async generator
async def stream_results(query: str) -> AsyncIterator[dict]:
async with get_connection() as conn:
async for row in conn.execute(query):
yield dict(row)
# Concurrent execution
async def fetch_all(urls: list[str]) -> list[Response]:
async with aiohttp.ClientSession() as session:
tasks = [fetch_one(session, url) for url in urls]
return await asyncio.gather(*tasks)
Testing
import pytest
from unittest.mock import Mock, patch, AsyncMock
# Fixtures
@pytest.fixture
def sample_user():
return User(id=1, name="Test", email="test@example.com")
@pytest.fixture
def mock_db():
with patch("myapp.database.get_connection") as mock:
yield mock
# Parametrized tests
@pytest.mark.parametrize("input,expected", [
("hello", "HELLO"),
("World", "WORLD"),
("", ""),
])
def test_uppercase(input: str, expected: str):
assert uppercase(input) == expected
# Async tests
@pytest.mark.asyncio
async def test_async_fetch():
result = await fetch_data("http://example.com")
assert result.status == 200
# Exception testing
def test_invalid_input_raises():
with pytest.raises(ValueError, match="must be positive"):
process_value(-1)
Project Structure
myproject/
├── src/
│ └── myproject/
│ ├── __init__.py
│ ├── core/ # Business logic
│ ├── api/ # API layer
│ ├── models/ # Data models
│ └── utils/ # Utilities
├── tests/
│ ├── conftest.py # Shared fixtures
│ ├── unit/
│ └── integration/
├── pyproject.toml # Project config
├── README.md
└── .env.example
Dependencies
# pyproject.toml
[project]
name = "myproject"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
"pydantic>=2.0",
"httpx>=0.24",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0",
"pytest-asyncio>=0.21",
"ruff>=0.1",
"mypy>=1.0",
]
[tool.ruff]
line-length = 88
target-version = "py311"
[tool.mypy]
strict = true
Common Anti-Patterns to Avoid
-
Mutable default arguments
python# Bad def add_item(item, items=[]): items.append(item) return items # Good def add_item(item, items=None): if items is None: items = [] items.append(item) return items -
Using
type()for type checkingpython# Bad if type(x) == list: # Good if isinstance(x, list): -
Catching too broadly
python# Bad except Exception: # Good except (ValueError, TypeError): -
String concatenation in loops
python# Bad result = "" for item in items: result += str(item) # Good result = "".join(str(item) for item in items)
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
typescript-best-practices
TypeScript development best practices, patterns, and conventions. Use when writing TypeScript code, reviewing .ts/.tsx files, discussing type safety, generics, utility types, or TypeScript project configuration. Triggers on mentions of TypeScript, tsconfig, type inference, generics, discriminated unions, React TypeScript.
api-design
REST and GraphQL API design patterns, best practices, and conventions. Use when designing APIs, discussing HTTP methods, status codes, versioning, or API documentation. Triggers on mentions of REST, API, GraphQL, endpoint, HTTP methods, OpenAPI, swagger, API versioning.
testing-patterns
Software testing patterns, strategies, and best practices. Use when writing tests, discussing test architecture, mocking, fixtures, or test organization. Triggers on mentions of testing, unit tests, integration tests, pytest, jest, mocking, fixtures, TDD, test coverage.
security-checklist
Application security best practices and vulnerability prevention. Use when reviewing code for security issues, implementing authentication, or discussing OWASP vulnerabilities. Triggers on mentions of security, authentication, authorization, XSS, SQL injection, CSRF, OWASP, encryption, secrets.
memory-generator
Generate CLAUDE.md project memory files by exploring codebases. Use when user asks to "generate memory", "create CLAUDE.md", "document this project", "understand this codebase", or starts work on a new/unfamiliar repository. Triggers on new project onboarding and documentation requests.
go-best-practices
Go development best practices, patterns, and conventions. Use when writing Go code, reviewing .go files, discussing goroutines, channels, error handling, or Go project structure. Triggers on mentions of Go, Golang, goroutines, channels, defer, interfaces, go mod.
Didn't find tool you were looking for?