python-patterns
Python-specific design patterns and best practices including protocols, dataclasses, context managers, decorators, async/await, type hints, and package organization. Use when working with Python code to apply Pythonic patterns.
About this skill
This skill provides an AI agent with the capability to generate, refactor, and review Python code, strictly adhering to modern Pythonic conventions and best practices. It encompasses a wide array of advanced Python features and design patterns such as `typing.Protocol` for structural subtyping, `dataclasses` for efficient data class creation, `context managers` for safe resource handling, `decorators` for extending functionality, `async/await` for asynchronous programming, comprehensive `type hints` for static analysis, and guidelines for optimal Python package organization. Primarily designed for the Claude AI agent as part of the `everything-claude-code` repository, this skill aims to elevate code quality by applying robust, production-grade patterns, making Python solutions more maintainable, scalable, and readable. It guides the AI in crafting code that is not just functional, but truly idiomatic Python.
Best use case
When an AI agent needs to generate or refactor Python code, ensuring it adheres to modern Pythonic conventions, best practices, and robust design patterns for maintainability, performance, and scalability.
Python-specific design patterns and best practices including protocols, dataclasses, context managers, decorators, async/await, type hints, and package organization. Use when working with Python code to apply Pythonic patterns.
Well-structured, idiomatic, and robust Python code that leverages modern language features and design patterns. The resulting code will be more maintainable, scalable, readable, and aligned with Python's best practices, enhancing overall software quality.
Practical example
Example input
Generate a Python class for a `UserService` that uses a `Repository` protocol for data access. The `Repository` should have `find_by_id(user_id: str)` and `save(user: dict)` methods. Ensure the `UserService` handles user retrieval and saving, returning `None` if a user is not found.
Example output
```python
from typing import Protocol, Optional, Dict
# Define the Repository Protocol for structural subtyping
class UserRepository(Protocol):
def find_by_id(self, user_id: str) -> Optional[Dict[str, str]]: ...
def save(self, user: Dict[str, str]) -> Dict[str, str]: ...
# Implement a concrete repository (e.g., for an in-memory store)
class InMemoryUserRepository:
def __init__(self):
self._users: Dict[str, Dict[str, str]] = {}
def find_by_id(self, user_id: str) -> Optional[Dict[str, str]]:
return self._users.get(user_id)
def save(self, user: Dict[str, str]) -> Dict[str, str]:
user_id = user.get("id") # Assuming user dict has an 'id'
if user_id:
self._users[user_id] = user
return user
raise ValueError("User must have an 'id' to be saved.")
# The UserService that depends on the UserRepository Protocol
class UserService:
def __init__(self, user_repo: UserRepository):
self.user_repo = user_repo
def get_user(self, user_id: str) -> Optional[Dict[str, str]]:
"""Retrieves a user by ID. Returns None if not found."""
return self.user_repo.find_by_id(user_id)
def create_user(self, user_data: Dict[str, str]) -> Dict[str, str]:
"""Creates a new user and saves it."""
if "id" not in user_data:
raise ValueError("User data must include an 'id' for creation.")
return self.user_repo.save(user_data)
# Example Usage:
# repo = InMemoryUserRepository()
# user_service = UserService(repo)
#
# new_user = {"id": "user123", "name": "Alice", "email": "alice@example.com"}
# saved_user = user_service.create_user(new_user)
# print(f"Saved user: {saved_user}")
#
# retrieved_user = user_service.get_user("user123")
# print(f"Retrieved user: {retrieved_user}")
#
# non_existent_user = user_service.get_user("user456")
# print(f"Non-existent user: {non_existent_user}")
```When to use this skill
- Generating new Python functions, classes, or modules that follow idiomatic Python.
- Refactoring existing Python code to improve its adherence to Pythonic principles, readability, and maintainability.
- Implementing complex features requiring advanced Python constructs like asynchronous operations, resource management, or structural typing.
- Ensuring type safety and clarity in Python code through consistent application of type hints.
When not to use this skill
- Working with programming languages other than Python.
- For extremely simple, one-off Python scripts where the overhead of applying advanced patterns is unnecessary.
- When the primary goal is debugging code without modifying its underlying architectural patterns.
- When a quick, minimal implementation is preferred over a robust, Pythonic one (though this is rarely a good practice).
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/python-patterns/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How python-patterns Compares
| Feature / Agent | python-patterns | Standard Approach |
|---|---|---|
| Platform Support | Claude | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | easy | N/A |
Frequently Asked Questions
What does this skill do?
Python-specific design patterns and best practices including protocols, dataclasses, context managers, decorators, async/await, type hints, and package organization. Use when working with Python code to apply Pythonic patterns.
Which AI agents support this skill?
This skill is designed for Claude.
How difficult is it to install?
The installation complexity is rated as easy. You can find the installation instructions above.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
AI Agents for Coding
Browse AI agent skills for coding, debugging, testing, refactoring, code review, and developer workflows across Claude, Cursor, and Codex.
Best AI Skills for Claude
Explore the best AI skills for Claude and Claude Code across coding, research, workflow automation, documentation, and agent operations.
AI Agent for Product Research
Browse AI agent skills for product research, competitive analysis, customer discovery, and structured product decision support.
SKILL.md Source
# Python Patterns
> This skill provides comprehensive Python patterns extending common design principles with Python-specific idioms.
## Protocol (Duck Typing)
Use `Protocol` for structural subtyping (duck typing with type hints):
```python
from typing import Protocol
class Repository(Protocol):
def find_by_id(self, id: str) -> dict | None: ...
def save(self, entity: dict) -> dict: ...
# Any class with these methods satisfies the protocol
class UserRepository:
def find_by_id(self, id: str) -> dict | None:
# implementation
pass
def save(self, entity: dict) -> dict:
# implementation
pass
def process_entity(repo: Repository, id: str) -> None:
entity = repo.find_by_id(id)
# ... process
```
**Benefits:**
- Type safety without inheritance
- Flexible, loosely coupled code
- Easy testing and mocking
## Dataclasses as DTOs
Use `dataclass` for data transfer objects and value objects:
```python
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class CreateUserRequest:
name: str
email: str
age: Optional[int] = None
tags: list[str] = field(default_factory=list)
@dataclass(frozen=True)
class User:
"""Immutable user entity"""
id: str
name: str
email: str
```
**Features:**
- Auto-generated `__init__`, `__repr__`, `__eq__`
- `frozen=True` for immutability
- `field()` for complex defaults
- Type hints for validation
## Context Managers
Use context managers (`with` statement) for resource management:
```python
from contextlib import contextmanager
from typing import Generator
@contextmanager
def database_transaction(db) -> Generator[None, None, None]:
"""Context manager for database transactions"""
try:
yield
db.commit()
except Exception:
db.rollback()
raise
# Usage
with database_transaction(db):
db.execute("INSERT INTO users ...")
```
**Class-based context manager:**
```python
class FileProcessor:
def __init__(self, filename: str):
self.filename = filename
self.file = None
def __enter__(self):
self.file = open(self.filename, 'r')
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
return False # Don't suppress exceptions
```
## Generators
Use generators for lazy evaluation and memory-efficient iteration:
```python
def read_large_file(filename: str):
"""Generator for reading large files line by line"""
with open(filename, 'r') as f:
for line in f:
yield line.strip()
# Memory-efficient processing
for line in read_large_file('huge.txt'):
process(line)
```
**Generator expressions:**
```python
# Instead of list comprehension
squares = (x**2 for x in range(1000000)) # Lazy evaluation
# Pipeline pattern
numbers = (x for x in range(100))
evens = (x for x in numbers if x % 2 == 0)
squares = (x**2 for x in evens)
```
## Decorators
### Function Decorators
```python
from functools import wraps
import time
def timing(func):
"""Decorator to measure execution time"""
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.2f}s")
return result
return wrapper
@timing
def slow_function():
time.sleep(1)
```
### Class Decorators
```python
def singleton(cls):
"""Decorator to make a class a singleton"""
instances = {}
@wraps(cls)
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Config:
pass
```
## Async/Await
### Async Functions
```python
import asyncio
from typing import List
async def fetch_user(user_id: str) -> dict:
"""Async function for I/O-bound operations"""
await asyncio.sleep(0.1) # Simulate network call
return {"id": user_id, "name": "Alice"}
async def fetch_all_users(user_ids: List[str]) -> List[dict]:
"""Concurrent execution with asyncio.gather"""
tasks = [fetch_user(uid) for uid in user_ids]
return await asyncio.gather(*tasks)
# Run async code
asyncio.run(fetch_all_users(["1", "2", "3"]))
```
### Async Context Managers
```python
class AsyncDatabase:
async def __aenter__(self):
await self.connect()
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
await self.disconnect()
async with AsyncDatabase() as db:
await db.query("SELECT * FROM users")
```
## Type Hints
### Advanced Type Hints
```python
from typing import TypeVar, Generic, Callable, ParamSpec, Concatenate
T = TypeVar('T')
P = ParamSpec('P')
class Repository(Generic[T]):
"""Generic repository pattern"""
def __init__(self, entity_type: type[T]):
self.entity_type = entity_type
def find_by_id(self, id: str) -> T | None:
# implementation
pass
# Type-safe decorator
def log_call(func: Callable[P, T]) -> Callable[P, T]:
@wraps(func)
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
```
### Union Types (Python 3.10+)
```python
def process(value: str | int | None) -> str:
match value:
case str():
return value.upper()
case int():
return str(value)
case None:
return "empty"
```
## Dependency Injection
### Constructor Injection
```python
class UserService:
def __init__(
self,
repository: Repository,
logger: Logger,
cache: Cache | None = None
):
self.repository = repository
self.logger = logger
self.cache = cache
def get_user(self, user_id: str) -> User | None:
if self.cache:
cached = self.cache.get(user_id)
if cached:
return cached
user = self.repository.find_by_id(user_id)
if user and self.cache:
self.cache.set(user_id, user)
return user
```
## Package Organization
### Project Structure
```
project/
├── src/
│ └── mypackage/
│ ├── __init__.py
│ ├── domain/ # Business logic
│ │ ├── __init__.py
│ │ └── models.py
│ ├── services/ # Application services
│ │ ├── __init__.py
│ │ └── user_service.py
│ └── infrastructure/ # External dependencies
│ ├── __init__.py
│ └── database.py
├── tests/
│ ├── unit/
│ └── integration/
├── pyproject.toml
└── README.md
```
### Module Exports
```python
# __init__.py
from .models import User, Product
from .services import UserService
__all__ = ['User', 'Product', 'UserService']
```
## Error Handling
### Custom Exceptions
```python
class DomainError(Exception):
"""Base exception for domain errors"""
pass
class UserNotFoundError(DomainError):
"""Raised when user is not found"""
def __init__(self, user_id: str):
self.user_id = user_id
super().__init__(f"User {user_id} not found")
class ValidationError(DomainError):
"""Raised when validation fails"""
def __init__(self, field: str, message: str):
self.field = field
self.message = message
super().__init__(f"{field}: {message}")
```
### Exception Groups (Python 3.11+)
```python
try:
# Multiple operations
pass
except* ValueError as eg:
# Handle all ValueError instances
for exc in eg.exceptions:
print(f"ValueError: {exc}")
except* TypeError as eg:
# Handle all TypeError instances
for exc in eg.exceptions:
print(f"TypeError: {exc}")
```
## Property Decorators
```python
class User:
def __init__(self, name: str):
self._name = name
self._email = None
@property
def name(self) -> str:
"""Read-only property"""
return self._name
@property
def email(self) -> str | None:
return self._email
@email.setter
def email(self, value: str) -> None:
if '@' not in value:
raise ValueError("Invalid email")
self._email = value
```
## Functional Programming
### Higher-Order Functions
```python
from functools import reduce
from typing import Callable, TypeVar
T = TypeVar('T')
U = TypeVar('U')
def pipe(*functions: Callable) -> Callable:
"""Compose functions left to right"""
def inner(arg):
return reduce(lambda x, f: f(x), functions, arg)
return inner
# Usage
process = pipe(
str.strip,
str.lower,
lambda s: s.replace(' ', '_')
)
result = process(" Hello World ") # "hello_world"
```
## When to Use This Skill
- Designing Python APIs and packages
- Implementing async/concurrent systems
- Structuring Python projects
- Writing Pythonic code
- Refactoring Python codebases
- Type-safe Python developmentRelated Skills
swiftui-patterns
SwiftUI 架构模式,使用 @Observable 进行状态管理,视图组合,导航,性能优化,以及现代 iOS/macOS UI 最佳实践。
perl-patterns
现代 Perl 5.36+ 的惯用法、最佳实践和约定,用于构建稳健、可维护的 Perl 应用程序。
kotlin-ktor-patterns
Ktor 服务器模式,包括路由 DSL、插件、身份验证、Koin DI、kotlinx.serialization、WebSockets 和 testApplication 测试。
kotlin-exposed-patterns
JetBrains Exposed ORM 模式,包括 DSL 查询、DAO 模式、事务、HikariCP 连接池、Flyway 迁移和仓库模式。
rust-patterns
Idiomatic Rust patterns, ownership, error handling, traits, concurrency, and best practices for building safe, performant applications.
laravel-patterns
Laravel architecture patterns, routing/controllers, Eloquent ORM, service layers, queues, events, caching, and API resources for production apps.
springboot-patterns
Spring Boot architecture patterns, REST API design, layered services, data access, caching, async processing, and logging. Use for Java Spring Boot backend work.
jpa-patterns
JPA/Hibernate patterns for entity design, relationships, query optimization, transactions, auditing, indexing, pagination, and pooling in Spring Boot.
django-patterns
Django architecture patterns, REST API design with DRF, ORM best practices, caching, signals, middleware, and production-grade Django apps.
python-testing
Python testing best practices using pytest including fixtures, parametrization, mocking, coverage analysis, async testing, and test organization. Use when writing or improving Python tests.
postgres-patterns
PostgreSQL database patterns for query optimization, schema design, indexing, and security. Quick reference for common patterns, index types, data types, and anti-pattern detection. Based on Supabase best practices.
golang-patterns
Go-specific design patterns and best practices including functional options, small interfaces, dependency injection, concurrency patterns, error handling, and package organization. Use when working with Go code to apply idiomatic Go patterns.