Communitygithub.com

Python開発パターン

Python のイディオム、PEP 8 標準、型ヒント、ベストプラクティスをまとめたスキル。堅牢で効率的かつ保守性の高い Python アプリケーションを構築するために、Python コードの作成やレビュー時、また慣用的な構造や型付け、PEP 8 に関する疑問がある場合に使用します。

Python開発パターン とは?

このスキルは、Claude Code や Cursor などの AI エージェントが Python コードを記述・レビュー・リファクタリングする際に参照する包括的な開発パターン集です。Python のイディオム(EAFP、明示性・可読性の重視など)から、型ヒント(基本アノテーション、PEP 604 以降の最新構文、Protocol によるダックタイピング)、エラーハンドリング(特例ハンドリング、例外連鎖、カスタム例外階層)、コンテキストマネージャ、内包表記とジェネレータ、データクラス、NamedTuple、デコレータ(関数・パラメータ化・クラスベース)、並行処理(スレッド・マルチプロセス・async/await)、パッケージ構成、メモリ・パフォーマンス最適化(__slots__、generator、文字列結合の効率化)まで、プロダクション品質の Python コードを書くための実践的なベストプラクティスを提供します。また、black、isort、ruff、mypy、pytest など主要なツールチェーンとの統合コマンドも含まれており、コード品質と保守性を高めるためのワンストップガイドとして機能します。

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

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Python開発パターン は何をしますか?

慣用的なPythonパターンとベストプラクティス。堅牢で効率的かつ保守性の高いアプリケーションを構築するための指針です。

いつアクティブにするか

  • 新しいPythonコードを書くとき
  • Pythonコードをレビューするとき
  • 既存のPythonコードをリファクタリングするとき
  • Pythonパッケージ/モジュールを設計するとき

基本原則

1. 可読性が重要

Pythonは可読性を重視します。コードは明確で理解しやすくなければなりません。

# Good: 明確で読みやすい
def get_active_users(users: list[User]) -> list[User]:
    """与えられたリストからアクティブなユーザーのみを返す。"""
    return [user for user in users if user.is_active]


# Bad: 巧妙だが混乱を招く
def get_active_users(u):
    return [x for x in u if x.a]

2. 暗黙よりも明示

マジックを避け、コードが何を行っているか明確にしましょう。

# Good: 明示的な設定
import logging

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

# Bad: 隠れた副作用
import some_module
some_module.setup()  # これは何をする?

3. EAFP - 許しを請うのは許可を得るより簡単

Pythonは条件チェックよりも例外処理を好みます。

# Good: EAFPスタイル
def get_value(dictionary: dict, key: str, default_value: Any = None) -> Any:
    try:
        return dictionary[key]
    except KeyError:
        return default_value

# Bad: LBYL(跳ぶ前に見よ)スタイル
def get_value(dictionary: dict, key: str, default_value: Any = None) -> Any:
    if key in dictionary:
        return dictionary[key]
    else:
        return default_value

型ヒント

基本的な型アノテーション

from typing import Optional, List, Dict, Any

def process_user(
    user_id: str,
    data: Dict[str, Any],
    active: bool = True
) -> Optional[User]:
    """ユーザーを処理し、更新されたUserまたはNoneを返す。"""
    if not active:
        return None
    return User(user_id, data)

モダンな型ヒント (Python 3.9以降)

# Python 3.9以上 - 組み込み型を使用
def process_items(items: list[str]) -> dict[str, int]:
    return {item: len(item) for item in items}

# Python 3.8以前 - typingモジュールを使用
from typing import List, Dict

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

型エイリアスとTypeVar

from typing import TypeVar, Union

# 複雑な型のエイリアス
JSON = Union[dict[str, Any], list[Any], str, int, float, bool, None]

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

# ジェネリック型
T = TypeVar('T')

def first(items: list[T]) -> T | None:
    """最初の要素を返す。リストが空の場合はNone。"""
    return items[0] if items else None

Protocolベースのダックタイピング

from typing import Protocol

class Renderable(Protocol):
    def render(self) -> str:
        """オブジェクトを文字列にレンダリングする。"""

def render_all(items: list[Renderable]) -> str:
    """Renderableプロトコルを実装するすべてのアイテムをレンダリングする。"""
    return "\n".join(item.render() for item in items)

エラーハンドリングパターン

特定の例外の処理

# Good: 特定の例外をキャッチ
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"設定ファイルが見つかりません: {path}") from e
    except json.JSONDecodeError as e:
        raise ConfigError(f"設定ファイル内のJSONが無効です: {path}") from e

# Bad: むき出しのexcept
def load_config(path: str) -> Config:
    try:
        with open(path) as f:
            return Config.from_json(f.read())
    except:
        return None  # 静かな失敗!

例外チェーン

def process_data(data: str) -> Result:
    try:
        parsed = json.loads(data)
    except json.JSONDecodeError as e:
        # 例外をチェーンしてトレースバックを保持
        raise ValueError(f"データの解析に失敗しました: {data}") from e

カスタム例外階層

class AppError(Exception):
    """すべてのアプリケーションエラーの基底例外。"""
    pass

class ValidationError(AppError):
    """入力値の検証に失敗した場合に発生。"""
    pass

class NotFoundError(AppError):
    """要求されたリソースが見つからない場合に発生。"""
    pass

# 使用例
def get_user(user_id: str) -> User:
    user = db.find_user(user_id)
    if not user:
        raise NotFoundError(f"ユーザーが見つかりません: {user_id}")
    return user

コンテキストマネージャ

リソース管理

# Good: コンテキストマネージャを使用
def process_file(path: str) -> str:
    with open(path, 'r') as f:
        return f.read()

# Bad: 手動リソース管理
def process_file(path: str) -> str:
    f = open(path, 'r')
    try:
        return f.read()
    finally:
        f.close()

カスタムコンテキストマネージャ

from contextlib import contextmanager

@contextmanager
def timer(name: str):
    """コードブロックの実行時間を計測するコンテキストマネージャ。"""
    start = time.perf_counter()
    yield
    elapsed = time.perf_counter() - start
    print(f"{name} took {elapsed:.4f} seconds")

# 使用例
with timer("データ処理"):
    process_large_dataset()

コンテキストマネージャクラス

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  # 例外を抑制しない

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

内包表記とジェネレータ

リスト内包表記

# Good: 単純な変換にはリスト内包表記
names = [user.name for user in users if user.is_active]

# Bad: 手動ループ
names = []
for user in users:
    if user.is_active:
        names.append(user.name)

# 複雑な内包表記は展開すべき
# Bad: 複雑すぎる
result = [x * 2 for x in items if x > 0 if x % 2 == 0]

# Good: ジェネレータ関数を使用
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

ジェネレータ式

# Good: 遅延評価にはジェネレータ
total = sum(x * x for x in range(1_000_000))

# Bad: 大きな中間リストを作成
total = sum([x * x for x in range(1_000_000)])

ジェネレータ関数

def read_large_file(path: str) -> Iterator[str]:
    """大きなファイルを1行ずつ読み込む。"""
    with open(path) as f:
        for line in f:
            yield line.strip()

# 使用例
for line in read_large_file("huge.txt"):
    process(line)

データクラスと名前付きタプル

データクラス

from dataclasses import dataclass, field
from datetime import datetime

@dataclass
class User:
    """自動的に __init__, __repr__, __eq__ が生成されるユーザーエンティティ。"""
    id: str
    name: str
    email: str
    created_at: datetime = field(default_factory=datetime.now)
    is_active: bool = True

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

バリデーション付きデータクラス

@dataclass
class User:
    email: str
    age: int

    def __post_init__(self):
        # メールアドレスの形式を検証
        if "@" not in self.email:
            raise ValueError(f"無効なメールアドレス: {self.email}")
        # 年齢の範囲を検証
        if self.age < 0 or self.age > 150:
            raise ValueError(f"無効な年齢: {self.age}")

名前付きタプル

from typing import NamedTuple

class Point(NamedTuple):
    """不変な2次元座標。"""
    x: float
    y: float

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

# 使用例
p1 = Point(0, 0)
p2 = Point(3, 4)
print(p1.distance(p2))  # 5.0

デコレータ

関数デコレータ

import functools
import time

def timer(func: Callable) -> Callable:
    """関数の実行時間を計測するデコレータ。"""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        elapsed = time.perf_counter() - start
        print(f"{func.__name__} took {elapsed:.4f}s")
        return result
    return wrapper

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

# slow_function() は次のように表示: slow_function took 1.0012s

パラメータ化されたデコレータ

def repeat(times: int):
    """関数を複数回繰り返すデコレータ。"""
    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"Hello, {name}!"

# greet("Alice") は ["Hello, Alice!", "Hello, Alice!", "Hello, Alice!"] を返す

クラスベースのデコレータ

class CountCalls:
    """関数が呼び出された回数をカウントするデコレータ。"""
    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__} has been called {self.count} times")
        return self.func(*args, **kwargs)

@CountCalls
def process():
    pass

# process() を呼ぶたびに呼び出し回数が表示される

並行処理パターン

I/Oバウンドタスクのスレッド化

import concurrent.futures
import threading

def fetch_url(url: str) -> str:
    """URLを取得する (I/Oバウンド操作)。"""
    import urllib.request
    with urllib.request.urlopen(url) as response:
        return response.read().decode()

def fetch_all_urls(urls: list[str]) -> dict[str, str]:
    """複数のURLをスレッドを使って並行して取得する。"""
    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"Error: {e}"
    return results

CPUバウンドタスクのマルチプロセス

def process_data(data: list[int]) -> int:
    """CPU負荷の高い計算。"""
    return sum(x ** 2 for x in data)

def process_all(datasets: list[list[int]]) -> list[int]:
    """複数のデータセットを複数プロセスで処理する。"""
    with concurrent.futures.ProcessPoolExecutor() as executor:
        results = list(executor.map(process_data, datasets))
    return results

非同期I/OのためのAsync/Await

import asyncio

async def fetch_async(url: str) -> str:
    """非同期にURLを取得する。"""
    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]:
    """複数のURLを並行して取得する。"""
    tasks = [fetch_async(url) for url in urls]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    return dict(zip(urls, results))

パッケージ構成

標準的なプロジェクトレイアウト

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

インポートの慣習

# Good: インポート順 - 標準ライブラリ、サードパーティ、ローカル
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

# Good: isortを使って自動インポートソート
# pip install isort

パッケージエクスポート用の init.py

# mypackage/__init__.py
"""mypackage - サンプルPythonパッケージ。"""

__version__ = "1.0.0"

# 主要なクラス/関数をパッケージレベルでエクスポート
from mypackage.models import User, Post
from mypackage.utils import format_name

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

メモリとパフォーマンス

メモリ効率のための slots

# Bad: 通常のクラスは __dict__ を使用(より多くのメモリ)
class Point:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

# Good: __slots__ によりメモリ使用量を削減
class Point:
    __slots__ = ['x', 'y']

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

大規模データ向けジェネレータ

# Bad: すべての行をメモリに格納したリストを返す
def read_lines(path: str) -> list[str]:
    with open(path) as f:
        return [line.strip() for line in f]

# Good: 行を1行ずつ生成する
def read_lines(path: str) -> Iterator[str]:
    with open(path) as f:
        for line in f:
            yield line.strip()

ループ内での文字列連結を避ける

# Bad: 文字列の不変性により O(n²)
result = ""
for item in items:
    result += str(item)

# Good: join を使用して O(n)
result = "".join(str(item) for item in items)

# Good: 構築には StringIO を使用
from io import StringIO

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

Pythonツールチェーンとの統合

必須コマンド

# コードフォーマット
black .
isort .

# リンター
ruff check .

# 型チェック
mypy .

# テスト
pytest

# 依存関係管理
pip install -r requirements.txt
# または poetry / uv
poetry install
uv pip install -r pyproject.toml

# 仮想環境
python -m venv venv
source venv/bin/activate  # Linux/macOS
venv\Scripts\activate  # Windows

pip の代わりに推奨

# uv - 高速なPythonパッケージインストーラ
curl -LsSf https://astral.sh/uv/install.sh | sh
uv pip install -r requirements.txt

# rye - Pythonプロジェクト管理
pipx install rye
rye init myproject
rye sync

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.

関連スキル