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.

144,923 stars
Complexity: easy

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

$curl -o ~/.claude/skills/python-patterns/SKILL.md --create-dirs "https://raw.githubusercontent.com/affaan-m/everything-claude-code/main/.kiro/skills/python-patterns/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/python-patterns/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How python-patterns Compares

Feature / Agentpython-patternsStandard Approach
Platform SupportClaudeLimited / Varies
Context Awareness High Baseline
Installation ComplexityeasyN/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

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 development

Related Skills

swiftui-patterns

144923
from affaan-m/everything-claude-code

SwiftUI 架构模式,使用 @Observable 进行状态管理,视图组合,导航,性能优化,以及现代 iOS/macOS UI 最佳实践。

DevelopmentClaude

perl-patterns

144923
from affaan-m/everything-claude-code

现代 Perl 5.36+ 的惯用法、最佳实践和约定,用于构建稳健、可维护的 Perl 应用程序。

DevelopmentClaude

kotlin-ktor-patterns

144923
from affaan-m/everything-claude-code

Ktor 服务器模式,包括路由 DSL、插件、身份验证、Koin DI、kotlinx.serialization、WebSockets 和 testApplication 测试。

DevelopmentClaude

kotlin-exposed-patterns

144923
from affaan-m/everything-claude-code

JetBrains Exposed ORM 模式,包括 DSL 查询、DAO 模式、事务、HikariCP 连接池、Flyway 迁移和仓库模式。

DevelopmentClaude

rust-patterns

144923
from affaan-m/everything-claude-code

Idiomatic Rust patterns, ownership, error handling, traits, concurrency, and best practices for building safe, performant applications.

DevelopmentClaude

laravel-patterns

144923
from affaan-m/everything-claude-code

Laravel architecture patterns, routing/controllers, Eloquent ORM, service layers, queues, events, caching, and API resources for production apps.

DevelopmentClaude

springboot-patterns

144923
from affaan-m/everything-claude-code

Spring Boot architecture patterns, REST API design, layered services, data access, caching, async processing, and logging. Use for Java Spring Boot backend work.

DevelopmentClaude

jpa-patterns

144923
from affaan-m/everything-claude-code

JPA/Hibernate patterns for entity design, relationships, query optimization, transactions, auditing, indexing, pagination, and pooling in Spring Boot.

DevelopmentClaude

django-patterns

144923
from affaan-m/everything-claude-code

Django architecture patterns, REST API design with DRF, ORM best practices, caching, signals, middleware, and production-grade Django apps.

DevelopmentClaude

python-testing

144923
from affaan-m/everything-claude-code

Python testing best practices using pytest including fixtures, parametrization, mocking, coverage analysis, async testing, and test organization. Use when writing or improving Python tests.

DevelopmentClaude

postgres-patterns

144923
from affaan-m/everything-claude-code

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.

DevelopmentClaude

golang-patterns

144923
from affaan-m/everything-claude-code

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.

DevelopmentClaude