AgentSkillsCN

Python Design Patterns

当用户询问“设计模式”、“SOLID 原则”、“工厂模式”、“策略模式”、“观察者模式”、“组合 vs 继承”、“Python 式设计”、“单例替代方案”、“反模式”、“依赖注入”,或需要指导如何在 Python 中以惯用方式应用四人组模式时,应使用此技能。

SKILL.md
--- frontmatter
name: Python Design Patterns
description: >
  This skill should be used when the user asks about "design patterns",
  "SOLID principles", "factory pattern", "strategy pattern", "observer pattern",
  "composition vs inheritance", "Pythonic design", "singleton alternatives",
  "anti-patterns", "dependency injection", or needs guidance on applying
  Gang of Four patterns idiomatically in Python.

Python Design Patterns

Pythonic adaptations of GoF patterns, SOLID principles, and anti-patterns to avoid.

"Modern Python simply avoids the problems that the old design patterns were meant to solve." — Brandon Rhodes, PyCon 2025

Prerequisites: from __future__ import annotations, collections.abc for Callable/Iterator, structlog for logging.

Pattern Decision Table

NeedPatternPython Idiom
Multiple creation strategiesFactoryFunction or @classmethod
Complex object, many optionsBuilderdataclass + replace()
Interchangeable algorithmsStrategyPass Callable
Event notificationObserverCallback list
Lazy sequencesIteratorGenerator (yield)
Tree structuresCompositeRecursive dataclass
Memory optimizationFlyweight__slots__, lru_cache
Interface conversionAdapterWrapper class
Cross-cutting concernsDecorator@decorator
State machinesStateDict mapping or match
Shared configurationGlobal ObjectModule-level instance
Callbacks with statePrebound Methodobj.method, partial
None is valid valueSentinel_MISSING = object()

SOLID Quick Reference

PrincipleViolation SignFix
Single Responsibility"Manager" classSplit into focused classes
Open-Closedif/elif on typesDict of handlers + Protocol
Liskov SubstitutionNotImplementedErrorComposition over inheritance
Interface SegregationUnused interface methodsSmall Protocol classes
Dependency Inversionself.db = PostgresDB()Constructor injection

Anti-Patterns

Anti-PatternWhy BadPythonic Alternative
Singleton classModules ARE singletonsModule-level instance
Deep inheritanceCoupling, diamond problemComposition + Protocol
Java getters/settersBoilerplateDirect attrs, @property
God ObjectUntestable, SRP violationFocused services
Method without selfUnnecessary classModule-level function
Premature patternsOver-engineeringYAGNI - add when needed

Key Patterns

Factory & Strategy

python
# Factory: function returning instance
def create_connection(db_type: str) -> Connection:
    return {"postgres": PostgresConn, "sqlite": SQLiteConn}[db_type]()

# Strategy: pass functions, not strategy objects
def calculate_total(items: list[Item], pricing: Callable[[float], float]) -> float:
    return sum(pricing(i.price) for i in items)

Observer & Decorator

python
# Observer: callback list
@dataclass
class EventEmitter:
    _listeners: dict[str, list[Callable]] = field(default_factory=dict)
    def on(self, event: str, fn: Callable) -> None:
        self._listeners.setdefault(event, []).append(fn)
    def emit(self, event: str, *args) -> None:
        for fn in self._listeners.get(event, []): fn(*args)

# Decorator: @wraps for cross-cutting concerns
def timing(func):
    @wraps(func)
    def wrapper(*a, **kw):
        start = perf_counter()
        result = func(*a, **kw)
        log.info("timing", elapsed=perf_counter() - start)
        return result
    return wrapper

Global Object & Sentinel

python
# Global Object: module-level instance (not singleton class)
_config: Config | None = None
def get_config() -> Config:
    global _config
    if _config is None: _config = Config.from_env()
    return _config

# Sentinel: distinguish None from "not provided"
_MISSING = object()
def get(key: str, default: object = _MISSING) -> object:
    if (v := cache.get(key)) is not None: return v
    if default is _MISSING: raise KeyError(key)
    return default

Reference Files

FileContent
references/patterns.mdAll GoF patterns with examples
references/solid-anti.mdSOLID principles + anti-patterns
references/python-idioms.mdGlobal Object, Prebound Method, Sentinel

Related