Skip to main content

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.

Aller à l'installation

Informations de source

Dépôt
affaan-m/ECC
Dernière activité de la source
30 mars 2026 à 01:21
Langue détectée de SKILL.md
anglais
Étoiles
264 820
Forks
39 570

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
python-patterns
description
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.
metadata
{"origin":"ECC","globs":["**/*.py","**/*.pyi"]}
# 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
Voir sur GitHub