Communitygithub.com

Python 开发模式

Python 风格习惯、PEP 8 标准、类型提示以及构建健壮、高效且可维护的 Python 应用程序的最佳实践。适用于编写或审查 Python 代码,以及在涉及习惯用法、类型或 PEP 8 时使用。

Python 开发模式 是什么?

这是一个专注于 Python 开发模式和最佳实践的 AI 技能。它提供了一套全面的指导方针,用于编写符合习惯、可读性强且易于维护的 Python 代码。该技能覆盖了核心原则如“可读性至关重要”和“显式优于隐式”,以及“EAFP”错误处理模式。技能内容包括类型提示、错误处理、上下文管理器、推导式与生成器、数据类、装饰器、并发模式、包组织和性能优化等高级主题。该技能集成到 Black 和 Ruff 等工具中,并适用于任何编写或审查 Python 代码的场景,帮助开发者遵循 PEP 8 标准和现代 Python 最佳实践。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/python-patterns

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Python 开发模式 是做什么的?

用于构建健壮、高效且可维护应用程序的惯用 Python 模式和最佳实践。

何时激活

  • 编写新的 Python 代码
  • 审查 Python 代码
  • 重构现有的 Python 代码
  • 设计 Python 包/模块

核心原则

1. 可读性至关重要

Python 优先考虑可读性。代码应该清晰易懂。

# 好:清晰且可读
def get_active_users(users: list[User]) -> list[User]:
    """返回提供的列表中的活跃用户。"""
    return [user for user in users if user.is_active]


# 差:巧妙但令人困惑
def get_active_users(u):
    return [x for x in u if x.a]

2. 显式优于隐式

避免魔术行为;清楚地说明你的代码执行的操作。

# 好:显式配置
import logging

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

# 差:隐藏的副作用
import some_module
some_module.setup()  # 这是做什么的?

3. EAFP - 请求原谅比请求许可更容易

Python 更倾向于使用异常处理而不是检查条件。

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

# 差: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

基于协议的鸭子类型

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)

错误处理模式

特定异常处理

# 好:捕获特定异常
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

# 差:裸的 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

上下文管理器

资源管理

# 好:使用上下文管理器
def process_file(path: str) -> str:
    with open(path, 'r') as f:
        return f.read()

# 差:手动资源管理
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} 耗时 {elapsed:.4f} 秒")

# 用法
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)

推导式和生成器

列表推导式

# 好:简单转换的列表推导式
names = [user.name for user in users if user.is_active]

# 差:手动循环
names = []
for user in users:
    if user.is_active:
        names.append(user.name)

# 复杂的推导式应该被展开
# 差:过于复杂
result = [x * 2 for x in items if x > 0 if x % 2 == 0]

# 好:使用生成器函数
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

生成器表达式

# 好:用于惰性求值的生成器
total = sum(x * x for x in range(1_000_000))

# 差:创建大的中间列表
total = sum([x * x for x in range(1_000_000)])

生成器函数

def read_large_file(path: str) -> Iterator[str]:
    """逐行读取一个大文件。"""
    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):
    """不可变的二维点。"""
    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__} 耗时 {elapsed:.4f}s")
        return result
    return wrapper

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

# slow_function() 输出: slow_function 耗时 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__} 已被调用 {self.count} 次")
        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

导入约定

# 好:导入顺序 - 标准库、第三方、本地
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

# 好:使用 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 提高内存效率

# 差:常规类使用 __dict__(更多内存)
class Point:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

# 好:__slots__ 减少内存使用
class Point:
    __slots__ = ['x', 'y']

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

用于大数据集的生成器

# 差:在内存中返回完整列表
def read_lines(path: str) -> list[str]:
    with open(path) as f:
        return [line.strip() for line in f]

# 好:逐行生成

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

避免在循环中进行字符串拼接

# 差:O(n²) 由于字符串不可变性
result = ""
for item in items:
    result += str(item)

# 好:使用 join 实现 O(n)
result = "".join(str(item) for item in items)

# 好:使用 StringIO 进行构建
from io import StringIO

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

Python 工具集成

基本命令

# 代码格式化
black .
isort .

# 代码检查
ruff check .

# 类型检查
mypy --strict mypackage/

# 测试
pytest -v --cov=mypackage tests/

pyproject.toml 配置

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "mypackage"
version = "1.0.0"
requires-python = ">=3.9"

[tool.black]
line-length = 88
target-version = ['py39']

[tool.ruff]
line-length = 88
select = ["E", "F", "I", "W"]

[tool.pytest.ini_options]
testpaths = ["tests"]

[tool.mypy]
strict = true
python_version = "3.9"

文档字符串和注释

Docstring 风格

# 好:清晰的 Docstring
def calculate_mean(values: list[float]) -> float:
    """计算数字列表的均值。

    Args:
        values: 浮点数列表。

    Returns:
        数字的算术平均值。
    """
    return sum(values) / len(values)

# 差:无 Docstring
def calculate_mean(values):
    return sum(values) / len(values)

行内注释

# 好:解释“为什么”,而不是“什么”
# 如果休息时间长,使用指数退避避免速率限制
time.sleep(min(2 ** retries, 60))

# 差:解释明显的东西
# 增加重试次数
retries += 1

此技能背后的原则

此技能遵循 Python 软件基金会概述的 PEP 8 和 PEP 20(Python 之禅)。Python 社区内的良好设计模式在此捕获,以在任何 Python 上下文中促进可维护、高效且符合习惯的代码。

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/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

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.

相关技能