Communitygithub.com

python-patterns

Pythonische Idiome, PEP 8-Standards, Typannotationen und Best Practices für die Entwicklung robuster, effizienter und wartbarer Python-Anwendungen. Verwenden Sie dies beim Schreiben oder Überprüfen von Python-Code, wenn idiomatische Struktur, Typisierung oder PEP 8 infrage stehen.

Was ist python-patterns?

Dieses Skill bietet eine umfassende Sammlung von Python-Entwicklungsmustern und Best Practices, die auf PEP 8, Typannotationen und pythonische Idiome ausgerichtet sind. Es behandelt Kernprinzipien wie Lesbarkeit, Explizitheit und EAFP (Easier to Ask Forgiveness Than Permission). Das Skill enthält detaillierte Codebeispiele für moderne Typannotationen (Python 3.9+ und älter), Typaliase, Generics und protokollbasiertes Duck-Typing. Darüber hinaus werden Fehlerbehandlungsmuster (spezifische Ausnahmen, Exception Chaining, benutzerdefinierte Exception-Hierarchien), Kontextmanager (ressourcenorientiert und benutzerdefiniert), Comprehensions und Generatoren, Datenklassen und Named Tuples, Dekorateure (funktional, parametrisiert, klassenbasiert) sowie Nebenläufigkeitsmuster (Threading, Multiprocessing, Async/Await) detailliert beschrieben. Es unterstützt Plattformen wie Claude Code, Cursor und Codex und integriert Python-Tooling (Black, isort, Ruff, Pytest, Coverage) für automatisierte Codequalität.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/python-patterns

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Python-Entwicklungsmuster

Idiomatische Python-Muster und Best Practices für die Entwicklung robuster, effizienter und wartbarer Anwendungen.

Wann aktivieren

  • Beim Schreiben von neuem Python-Code
  • Beim Überprüfen von Python-Code
  • Beim Refactoring vorhandenen Python-Codes
  • Beim Entwerfen von Python-Paketen/-Modulen

Kernprinzipien

1. Lesbarkeit zählt

Python priorisiert Lesbarkeit. Code sollte offensichtlich und leicht verständlich sein.

# Gut: Klar und lesbar
def get_active_users(users: list[User]) -> list[User]:
    """Nur aktive Benutzer aus der bereitgestellten Liste zurückgeben."""
    return [user for user in users if user.is_active]


# Schlecht: Raffiniert, aber verwirrend
def get_active_users(u):
    return [x for x in u if x.a]

2. Explizit ist besser als implizit

Vermeiden Sie Magie; seien Sie klar darüber, was Ihr Code tut.

# Gut: Explizite Konfiguration
import logging

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

# Schlecht: Versteckte Seiteneffekte
import some_module
some_module.setup()  # Was macht das?

3. EAFP - Easier to Ask Forgiveness Than Permission (Besser um Vergebung als um Erlaubnis bitten)

Python bevorzugt Ausnahmebehandlung gegenüber Bedingungsprüfungen.

# Gut: EAFP-Stil
def get_value(dictionary: dict, key: str, default_value: Any = None) -> Any:
    try:
        return dictionary[key]
    except KeyError:
        return default_value

# Schlecht: LBYL (Look Before You Leap)-Stil
def get_value(dictionary: dict, key: str, default_value: Any = None) -> Any:
    if key in dictionary:
        return dictionary[key]
    else:
        return default_value

Typannotationen

Grundlegende Typannotationen

from typing import Optional, List, Dict, Any

def process_user(
    user_id: str,
    data: Dict[str, Any],
    active: bool = True
) -> Optional[User]:
    """Einen Benutzer verarbeiten und den aktualisierten Benutzer oder None zurückgeben."""
    if not active:
        return None
    return User(user_id, data)

Moderne Typannotationen (Python 3.9+)

# Python 3.9+ - Integrierte Typen verwenden
def process_items(items: list[str]) -> dict[str, int]:
    return {item: len(item) for item in items}

# Python 3.8 und älter - typing-Modul verwenden
from typing import List, Dict

def process_items(items: List[str]) -> Dict[str, int]:
    return {item: len(item) for item in items}

Typaliase und TypeVar

from typing import TypeVar, Union

# Typalias für komplexe Typen
JSON = Union[dict[str, Any], list[Any], str, int, float, bool, None]

def parse_json(data: str) -> JSON:
    return json.loads(data)

# Generische Typen
T = TypeVar('T')

def first(items: list[T]) -> T | None:
    """Das erste Element oder None zurückgeben, wenn die Liste leer ist."""
    return items[0] if items else None

Protokollbasiertes Duck-Typing

from typing import Protocol

class Renderable(Protocol):
    def render(self) -> str:
        """Das Objekt in einen String rendern."""

def render_all(items: list[Renderable]) -> str:
    """Alle Elemente rendern, die das Renderable-Protokoll implementieren."""
    return "\n".join(item.render() for item in items)

Fehlerbehandlungsmuster

Spezifische Ausnahmebehandlung

# Gut: Spezifische Ausnahmen abfangen
def load_config(path: str) -> Config:
    try:
        with open(path) as f:
            return Config.from_json(f.read())
    except FileNotFoundError as e:
        raise ConfigError(f"Konfigurationsdatei nicht gefunden: {path}") from e
    except json.JSONDecodeError as e:
        raise ConfigError(f"Ungültiges JSON in Konfiguration: {path}") from e

# Schlecht: Bloßes except

def load_config(path: str) -> Config:
    try:
        with open(path) as f:
            return Config.from_json(f.read())
    except:
        return None  # Stiller Fehlschlag!

Ausnahmeverkettung (Exception Chaining)

def process_data(data: str) -> Result:
    try:
        parsed = json.loads(data)
    except json.JSONDecodeError as e:
        # Ausnahmen verketten, um den Traceback zu erhalten
        raise ValueError(f"Daten konnten nicht geparst werden: {data}") from e

Benutzerdefinierte Ausnahmehierarchie

class AppError(Exception):
    """Basisausnahme für alle Anwendungsfehler."""
    pass

class ValidationError(AppError):
    """Wird ausgelöst, wenn die Eingabevalidierung fehlschlägt."""
    pass

class NotFoundError(AppError):
    """Wird ausgelöst, wenn eine angeforderte Ressource nicht gefunden wird."""
    pass

# Verwendung
def get_user(user_id: str) -> User:
    user = db.find_user(user_id)
    if not user:
        raise NotFoundError(f"Benutzer nicht gefunden: {user_id}")
    return user

Kontextmanager

Ressourcenverwaltung

# Gut: Kontextmanager verwenden
def process_file(path: str) -> str:
    with open(path, 'r') as f:
        return f.read()

# Schlecht: Manuelle Ressourcenverwaltung
def process_file(path: str) -> str:
    f = open(path, 'r')
    try:
        return f.read()
    finally:
        f.close()

Benutzerdefinierte Kontextmanager

from contextlib import contextmanager

@contextmanager
def timer(name: str):
    """Kontextmanager zur Zeitmessung eines Codeblocks."""
    start = time.perf_counter()
    yield
    elapsed = time.perf_counter() - start
    print(f"{name} dauerte {elapsed:.4f} Sekunden")

# Verwendung
with timer("Datenverarbeitung"):
    process_large_dataset()

Kontextmanager-Klassen

class DatabaseTransaction:
    def __init__(self, connection):
        self.connection = connection

    def __enter__(self):
        self.connection.begin_transaction()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is None:
            self.connection.commit()
        else:
            self.connection.rollback()
        return False  # Ausnahmen nicht unterdrücken

# Verwendung
with DatabaseTransaction(conn):
    user = conn.create_user(user_data)
    conn.create_profile(user.id, profile_data)

Comprehensions und Generatoren

Listen-Comprehensions

# Gut: Listen-Comprehension für einfache Transformationen
names = [user.name for user in users if user.is_active]

# Schlecht: Manuelle Schleife
names = []
for user in users:
    if user.is_active:
        names.append(user.name)

# Komplexe Comprehensions sollten erweitert werden
# Schlecht: Zu komplex
result = [x * 2 for x in items if x > 0 if x % 2 == 0]

# Gut: Generatorfunktion verwenden
def filter_and_transform(items: Iterable[int]) -> list[int]:
    result = []
    for x in items:
        if x > 0 and x % 2 == 0:
            result.append(x * 2)
    return result

Generator-Ausdrücke

# Gut: Generator für verzögerte Auswertung
total = sum(x * x for x in range(1_000_000))

# Schlecht: Erzeugt große Zwischenliste
total = sum([x * x for x in range(1_000_000)])

Generator-Funktionen

def read_large_file(path: str) -> Iterator[str]:
    """Eine große Datei zeilenweise lesen."""
    with open(path) as f:
        for line in f:
            yield line.strip()

# Verwendung
for line in read_large_file("huge.txt"):
    process(line)

Datenklassen und Named Tuples

Datenklassen

from dataclasses import dataclass, field
from datetime import datetime

@dataclass
class User:
    """Benutzer-Entität mit automatischem __init__, __repr__ und __eq__."""
    id: str
    name: str
    email: str
    created_at: datetime = field(default_factory=datetime.now)
    is_active: bool = True

# Verwendung
user = User(
    id="123",
    name="Alice",
    email="[email protected]"
)

Datenklassen mit Validierung

@dataclass
class User:
    email: str
    age: int

    def __post_init__(self):
        # E-Mail-Format validieren
        if "@" not in self.email:
            raise ValueError(f"Ungültige E-Mail: {self.email}")
        # Altersbereich validieren
        if self.age < 0 or self.age > 150:
            raise ValueError(f"Ungültiges Alter: {self.age}")

Named Tuples

from typing import NamedTuple

class Point(NamedTuple):
    """Unveränderlicher 2D-Punkt."""
    x: float
    y: float

    def distance(self, other: 'Point') -> float:
        return ((self.x - other.x) ** 2 + (self.y - other.y) ** 2) ** 0.5

# Verwendung
p1 = Point(0, 0)
p2 = Point(3, 4)
print(p1.distance(p2))  # 5.0

Dekorateure

Funktionsdekorateure

import functools
import time

def timer(func: Callable) -> Callable:
    """Dekorator zur Zeitmessung der Funktionsausführung."""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        elapsed = time.perf_counter() - start
        print(f"{func.__name__} dauerte {elapsed:.4f}s")
        return result
    return wrapper

@timer
def slow_function():
    time.sleep(1)

# slow_function() gibt aus: slow_function dauerte 1.0012s

Parametrisierte Dekorateure

def repeat(times: int):
    """Dekorator zum mehrmaligen Wiederholen einer Funktion."""
    def decorator(func: Callable) -> Callable:
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            results = []
            for _ in range(times):
                results.append(func(*args, **kwargs))
            return results
        return wrapper
    return decorator

@repeat(times=3)
def greet(name: str) -> str:
    return f"Hallo, {name}!"

# greet("Alice") gibt ["Hallo, Alice!", "Hallo, Alice!", "Hallo, Alice!"] zurück

Klassenbasierte Dekorateure

class CountCalls:
    """Dekorator, der zählt, wie oft eine Funktion aufgerufen wird."""
    def __init__(self, func: Callable):
        functools.update_wrapper(self, func)
        self.func = func
        self.count = 0

    def __call__(self, *args, **kwargs):
        self.count += 1
        print(f"{self.func.__name__} wurde {self.count} Mal aufgerufen")
        return self.func(*args, **kwargs)

@CountCalls
def process():
    pass

# Jeder Aufruf von process() gibt die Anzahl der Aufrufe aus

Nebenläufigkeitsmuster

Threading für I/O-gebundene Aufgaben

import concurrent.futures
import threading

def fetch_url(url: str) -> str:
    """Eine URL abrufen (I/O-gebundene Operation)."""
    import urllib.request
    with urllib.request.urlopen(url) as response:
        return response.read().decode()

def fetch_all_urls(urls: list[str]) -> dict[str, str]:
    """Mehrere URLs gleichzeitig mit Threads abrufen."""
    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        future_to_url = {executor.submit(fetch_url, url): url for url in urls}
        results = {}
        for future in concurrent.futures.as_completed(future_to_url):
            url = future_to_url[future]
            try:
                results[url] = future.result()
            except Exception as e:
                results[url] = f"Fehler: {e}"
    return results

Multiprocessing für CPU-gebundene Aufgaben

def process_data(data: list[int]) -> int:
    """CPU-intensive Berechnung."""
    return sum(x ** 2 for x in data)

def process_all(datasets: list[list[int]]) -> list[int]:
    """Mehrere Datensätze mit mehreren Prozessen verarbeiten."""
    with concurrent.futures.ProcessPoolExecutor() as executor:
        results = list(executor.map(process_data, datasets))
    return results

Async/Await für gleichzeitige I/O-Operationen

import asyncio

async def fetch_async(url: str) -> str:
    """Eine URL asynchron abrufen."""
    import aiohttp
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.text()

async def fetch_all(urls: list[str]) -> dict[str, str]:
    """Mehrere URLs gleichzeitig abrufen."""
    tasks = [fetch_async(url) for url in urls]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    return dict(zip(urls, results))

Paketorganisation

Standard-Projektstruktur

myproject/
├── src/
│   └── mypackage/
│       ├── __init__.py
│       ├── main.py
│       ├── api/
│       │   ├── __init__.py
│       │   └── routes.py
│       ├── models/
│       │   ├── __init__.py
│       │   └── user.py
│       └── utils/
│           ├── __init__.py
│           └── helpers.py
├── tests/
│   ├── __init__.py
│   ├── conftest.py
│   ├── test_api.py
│   └── test_models.py
├── pyproject.toml
├── README.md
└── .gitignore

Import-Konventionen

# Gut: Import-Reihenfolge - stdlib, Drittanbieter, lokal
import os
import sys
from pathlib import Path

import requests
from fastapi import FastAPI

from mypackage.models import User
from mypackage.utils import format_name

# Gut: isort für automatische Import-Sortierung verwenden
# pip install isort

init.py für Paket-Exporte

# mypackage/__init__.py
"""mypackage - Ein Beispiel-Python-Paket."""

__version__ = "1.0.0"

# Hauptklassen/-Funktionen auf Paketebene exportieren
from mypackage.models import User, Post
from mypackage.utils import format_name

__all__ = ["User", "Post", "format_name"]

Speicher und Leistung

Verwendung von slots für Speichereffizienz

# Schlecht: Normale Klasse verwendet __dict__ (mehr Speicher)
class Point:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

# Gut: __slots__ reduziert Speicherverbrauch
class Point:
    __slots__ = ['x', 'y']

    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

Generator für große Datenmengen

# Schlecht: Vollständige Liste im Speicher zurückgeben
def read_lines(path: str) -> list[str]:
    with open(path) as f:
        return [line.strip() for line in f]

# Gut: Zeilen einzeln ausliefern
def read_lines(path: str) -> Iterator[str]:
    with open(path) as f:
        for line in f:
            yield line.strip()

String-Verkettung in Schleifen vermeiden

# Schlecht: O(n²) aufgrund der Unveränderlichkeit von Strings
result = ""
for item in items:
    result += str(item)

# Gut: O(n) mit join
result = "".join(str(item) for item in items)

# Gut: StringIO für Aufbau verwenden
from io import StringIO

buffer = StringIO()
for item in items:
    buffer.write(str(item))
result = buffer.getvalue()

Python-Tooling-Integration

Wesentliche Befehle

# Code-Formatierung
black .
isort .

# Linting
ruff check .

# Statische Typüberprüfung
mypy src/

# Tests
pytest tests/ -v --cov=src --cov-report=term-missing

# Sicherheitschecks
bandit -r src/

# Abhängigkeitsverwaltung (pip-compile)
pip-compile requirements.in

# Build und Veröffentlichung
python -m build
twine upload dist/*

Konfigurationsbeispiele

# pyproject.toml
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"

[tool.black]
line-length = 88

[tool.isort]
profile = "black"

[tool.mypy]
python_version = "3.11"
warn_return_any = true
warn_unused_configs = true

[tool.pytest.ini_options]
minversion = "7.0"
addopts = "-ra -q"
testpaths = ["tests"]

[tool.coverage.run]
source = ["src"]

[tool.coverage.report]
exclude_lines = ["pragma: no cover"]

zusätzliche Ressourcen

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Verwandte Skills