
Python Patterns
- 7.4k installs
- 234k repo stars
- Updated July 27, 2026
- affaan-m/everything-claude-code
Python design patterns skill covering protocols, dataclasses, context managers, generators, decorators, async/await, type hints, dependency injection, package organization, and functional programming for Pythonic code
About
This skill provides Python-specific design patterns and best practices for developers writing Pythonic code. It covers protocols for duck typing with type hints, dataclasses for DTOs, context managers for resource handling, generators for memory efficiency, decorators for cross-cutting concerns, async/await patterns for concurrent I/O, advanced type hints including generics and ParamSpec, dependency injection, package organization, custom exceptions, property decorators, and functional programming utilities. Developers invoke this when structuring Python projects, designing APIs, implementing async systems, or refactoring codebases to use idiomatic Python patterns. The skill extends common design principles with Python-specific idioms like frozen dataclasses, contextlib decorators, and asyncio.gather for concurrent execution.
- Protocols enable structural subtyping without inheritance, providing type-safe duck typing for flexible interfaces
- Context managers handle resources with __enter__/__exit__ or @contextmanager decorator for automatic cleanup
- Generators and generator expressions provide lazy evaluation for memory-efficient processing of large datasets
- Advanced type hints include Generic[T], ParamSpec, and union types with pattern matching for type-safe APIs
- Async/await patterns with asyncio.gather enable concurrent I/O operations and async context managers
Python Patterns by the numbers
- 7,425 all-time installs (skills.sh)
- +341 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #6 of 311 Python skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
python-patterns capabilities & compatibility
- Capabilities
- protocol based duck typing · dataclass dtos · context managers · generators · decorators · async await · advanced type hints · dependency injection
- Use cases
- api development · refactoring
- Platforms
- macOS · Windows · Linux
- IDEs
- vscode · cursor ide · pycharm · intellij
- Runs
- Runs locally
- Pricing
- Free
npx skills add https://github.com/affaan-m/everything-claude-code --skill python-patternsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 7.4k |
|---|---|
| repo stars | ★ 234k |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 27, 2026 |
| Repository | affaan-m/everything-claude-code ↗ |
What it does
Apply Python-specific design patterns and idioms when building Python backends, APIs, or libraries.
Who is it for?
Python backend development, API design, library construction, async systems, refactoring legacy Python code to idiomatic patterns
Skip if: Non-Python languages, frontend-specific patterns, database schema design, deployment configuration
When should I use this skill?
Structuring Python projects, designing APIs or packages, implementing async/concurrent systems, refactoring to Pythonic patterns, writing type-safe Python code
What you get
Developers write Pythonic code using protocols for duck typing, dataclasses for DTOs, context managers for resources, generators for lazy evaluation, async/await for concurrency, and advanced type hints for type safety
- Type-safe Python code using protocols and generics
- memory-efficient generators
- async/await concurrent operations
By the numbers
- 5 major pattern categories: protocols, dataclasses, context managers, generators, async/await
- Python 3.10+ required for union types and match statements
- Python 3.11+ required for exception groups
Files
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):
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)
# ... processBenefits:
- Type safety without inheritance
- Flexible, loosely coupled code
- Easy testing and mocking
Dataclasses as DTOs
Use dataclass for data transfer objects and value objects:
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: strFeatures:
- Auto-generated
__init__,__repr__,__eq__ frozen=Truefor immutabilityfield()for complex defaults- Type hints for validation
Context Managers
Use context managers (with statement) for resource management:
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:
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 exceptionsGenerators
Use generators for lazy evaluation and memory-efficient iteration:
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:
# 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
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
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:
passAsync/Await
Async Functions
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
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
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 wrapperUnion Types (Python 3.10+)
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
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 userPackage 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.mdModule Exports
# __init__.py
from .models import User, Product
from .services import UserService
__all__ = ['User', 'Product', 'UserService']Error Handling
Custom Exceptions
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+)
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
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 = valueFunctional Programming
Higher-Order Functions
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 development
Related skills
Forks & variants (1)
Python Patterns has 1 known copy in the catalog totaling 1.5k installs. They canonicalize to this original listing.
- affaan-m - 1.5k installs
How it compares
Baseline Python idioms and PEP 8; pair with django-patterns or framework skills for web stack specifics.
FAQ
When should I use Protocol vs ABC for interfaces?
Use Protocol for structural subtyping without inheritance - any class with matching methods satisfies the protocol. Use ABC when you need explicit inheritance and shared implementation via abstract base classes.
How do I make a dataclass immutable?
Use @dataclass(frozen=True) decorator to create immutable dataclasses where all fields are read-only after initialization, suitable for value objects and entities.
What's the difference between generators and list comprehensions?
Generators use parentheses and provide lazy evaluation - values computed on-demand - making them memory-efficient for large datasets. List comprehensions use brackets and create entire lists in memory upfront.
Is Python Patterns safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.