当前位置:首页>python>Skills之Python设计模式与最佳实践指南 - 构建健壮高效代码 GitHub Stars 17.4万+

Skills之Python设计模式与最佳实践指南 - 构建健壮高效代码 GitHub Stars 17.4万+

  • 2026-10-11 08:15:22
Skills之Python设计模式与最佳实践指南 - 构建健壮高效代码 GitHub Stars 17.4万+

“该技能提供Python开发的核心设计模式与最佳实践,涵盖可读性、显式编程、EAFP原则、类型提示(包括现代类型注解和协议)以及错误处理模式。适用于编写、审查和重构Python代码,帮助开发者构建健壮、高效且可维护的应用程序,提升代码质量和开发效率。”

Python 开发模式

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

何时启用

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

核心原则

1. 可读性至关重要

Python 优先考虑可读性。代码应该清晰且易于理解。

# Good: Clear and readabledef get_active_users(users: list[User]) -> list[User]:    """Return only active users from the provided list."""    return [user for user in users if user.is_active]# Bad: Clever but confusingdef get_active_users(u):    return [x for x in u if x.a]

2. 显式优于隐式

避免魔法;明确你的代码在做什么。

# Good: Explicit configurationimport logginglogging.basicConfig(    level=logging.INFO,    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')# Bad: Hidden side effectsimport some_modulesome_module.setup()  # What does this do?

3. EAFP - 请求宽恕比请求许可更容易

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

# Good: EAFP styledef get_value(dictionary: dict, key: str) -> Any:    try:        return dictionary[key]    except KeyError:        return default_value# Bad: LBYL (Look Before You Leap) styledef get_value(dictionary: dict, key: str) -> Any:    if key in dictionary:        return dictionary[key]    else:        return default_value

类型提示

基础类型注解

from typing import Optional, List, Dict, Anydef process_user(    user_id: str,    data: Dict[str, Any],    active: bool = True) -> Optional[User]:    """Process a user and return the updated User or None."""    if not active:        return None    return User(user_id, data)

现代类型提示 (Python 3.9+)

# Python 3.9+ - Use built-in typesdef process_items(items: list[str]) -> dict[str, int]:    return {item: len(item) for item in items}# Python 3.8 and earlier - Use typing modulefrom typing import List, Dictdef process_items(items: List[str]) -> Dict[str, int]:    return {item: len(item) for item in items}

类型别名与 TypeVar

from typing import TypeVar, Union# Type alias for complex typesJSON = Union[dict[str, Any], list[Any], str, int, float, bool, None]def parse_json(data: str) -> JSON:    return json.loads(data)# Generic typesT = TypeVar('T')def first(items: list[T]) -> T | None:    """Return the first item or None if list is empty."""    return items[0] if items else None

基于协议的鸭子类型

from typing import Protocolclass Renderable(Protocol):    def render(self) -> str:        """Render the object to a string."""def render_all(items: list[Renderable]) -> str:    """Render all items that implement the Renderable protocol."""    return "\n".join(item.render() for item in items)

错误处理模式

特定异常处理

# Good: Catch specific exceptionsdef load_config(path: str) -> Config:    try:        with open(path) as f:            return Config.from_json(f.read())    except FileNotFoundError as e:        raise ConfigError(f"Config file not found: {path}") from e    except json.JSONDecodeError as e:        raise ConfigError(f"Invalid JSON in config: {path}") from e# Bad: Bare exceptdef load_config(path: str) -> Config:    try:        with open(path) as f:            return Config.from_json(f.read())    except:        return None  # Silent failure!

异常链

def process_data(data: str) -> Result:    try:        parsed = json.loads(data)    except json.JSONDecodeError as e:        # Chain exceptions to preserve the traceback        raise ValueError(f"Failed to parse data: {data}") from e

自定义异常层次结构

class AppError(Exception):    """Base exception for all application errors."""    passclass ValidationError(AppError):    """Raised when input validation fails."""    passclass NotFoundError(AppError):    """Raised when a requested resource is not found."""    pass# Usagedef get_user(user_id: str) -> User:    user = db.find_user(user_id)    if not user:        raise NotFoundError(f"User not found: {user_id}")    return user

上下文管理器

资源管理

# Good: Using context managersdef process_file(path: str) -> str:    with open(path, 'r') as f:        return f.read()# Bad: Manual resource managementdef process_file(path: str) -> str:    f = open(path, 'r')    try:        return f.read()    finally:        f.close()

自定义上下文管理器

from contextlib import contextmanager@contextmanagerdef timer(name: str):    """Context manager to time a block of code."""    start = time.perf_counter()    yield    elapsed = time.perf_counter() - start    print(f"{name} took {elapsed:.4f} seconds")# Usagewith timer("data processing"):    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  # Don't suppress exceptions# Usagewith DatabaseTransaction(conn):    user = conn.create_user(user_data)    conn.create_profile(user.id, profile_data)

推导式与生成器

列表推导式

# Good: List comprehension for simple transformationsnames = [user.name for user in users if user.is_active]# Bad: Manual loopnames = []for user in users:    if user.is_active:        names.append(user.name)# Complex comprehensions should be expanded# Bad: Too complexresult = [x * 2 for x in items if x > 0 if x % 2 == 0]# Good: Use a generator functiondef 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: Generator for lazy evaluationtotal = sum(x * x for x in range(1_000_000))# Bad: Creates large intermediate listtotal = sum([x * x for x in range(1_000_000)])

生成器函数

def read_large_file(path: str) -> Iterator[str]:    """Read a large file line by line."""    with open(path) as f:        for line in f:            yield line.strip()# Usagefor line in read_large_file("huge.txt"):    process(line)

数据类与命名元组

数据类

from dataclasses import dataclass, fieldfrom datetime import datetime@dataclassclass User:    """User entity with automatic __init__, __repr__, and __eq__."""    id: str    name: str    email: str    created_at: datetime = field(default_factory=datetime.now)    is_active: bool = True# Usageuser = User(    id="123",    name="Alice",    email="alice@example.com")

带验证的数据类

@dataclassclass User:    email: str    age: int    def __post_init__(self):        # Validate email format        if "@" not in self.email:            raise ValueError(f"Invalid email: {self.email}")        # Validate age range        if self.age < 0 or self.age > 150:            raise ValueError(f"Invalid age: {self.age}")

命名元组

from typing import NamedTupleclass Point(NamedTuple):    """Immutable 2D point."""    x: float    y: float    def distance(self, other: 'Point') -> float:        return ((self.x - other.x) ** 2 + (self.y - other.y) ** 2) ** 0.5# Usagep1 = Point(0, 0)p2 = Point(3, 4)print(p1.distance(p2))  # 5.0

装饰器

函数装饰器

import functoolsimport timedef timer(func: Callable) -> Callable:    """Decorator to time function execution."""    @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@timerdef slow_function():    time.sleep(1)# slow_function() prints: slow_function took 1.0012s

参数化装饰器

def repeat(times: int):    """Decorator to repeat a function multiple times."""    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") returns ["Hello, Alice!", "Hello, Alice!", "Hello, Alice!"]

基于类的装饰器

class CountCalls:    """Decorator that counts how many times a function is called."""    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)@CountCallsdef process():    pass# Each call to process() prints the call count

并发模式

用于 I/O 密集型任务的线程

import concurrent.futuresimport threadingdef fetch_url(url: str) -> str:    """Fetch a URL (I/O-bound 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]:    """Fetch multiple URLs concurrently using threads."""    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-intensive computation."""    return sum(x ** 2 for x in data)def process_all(datasets: list[list[int]]) -> list[int]:    """Process multiple datasets using multiple processes."""    with concurrent.futures.ProcessPoolExecutor() as executor:        results = list(executor.map(process_data, datasets))    return results

用于并发 I/O 的 Async/Await

import asyncioasync def fetch_async(url: str) -> str:    """Fetch a URL asynchronously."""    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]:    """Fetch multiple URLs concurrently."""    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 order - stdlib, third-party, localimport osimport sysfrom pathlib import Pathimport requestsfrom fastapi import FastAPIfrom mypackage.models import Userfrom mypackage.utils import format_name# Good: Use isort for automatic import sorting# pip install isort

init.py 用于包导出

# mypackage/__init__.py"""mypackage - A sample Python package."""__version__ = "1.0.0"# Export main classes/functions at package levelfrom mypackage.models import User, Postfrom mypackage.utils import format_name__all__ = ["User", "Post", "format_name"]

内存与性能

使用 slots 提高内存效率

# Bad: Regular class uses __dict__ (more memory)class Point:    def __init__(self, x: float, y: float):        self.x = x        self.y = y# Good: __slots__ reduces memory usageclass Point:    __slots__ = ['x', 'y']    def __init__(self, x: float, y: float):        self.x = x        self.y = y

生成器处理大数据

# Bad: Returns full list in memorydef read_lines(path: str) -> list[str]:    with open(path) as f:        return [line.strip() for line in f]# Good: Yields lines one at a timedef read_lines(path: str) -> Iterator[str]:    with open(path) as f:        for line in f:            yield line.strip()

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

# Bad: O(n²) due to string immutabilityresult = ""for item in items:    result += str(item)# Good: O(n) using joinresult = "".join(str(item) for item in items)# Good: Using StringIO for buildingfrom io import StringIObuffer = StringIO()for item in items:    buffer.write(str(item))result = buffer.getvalue()

Python 工具集成

基本命令

# Code formattingblack .isort .# Lintingruff check .pylint mypackage/# Type checkingmypy .# Testingpytest --cov=mypackage --cov-report=html# Security scanningbandit -r .# Dependency managementpip-auditsafety check

pyproject.toml 配置

[project]name = "mypackage"version = "1.0.0"requires-python = ">=3.9"dependencies = [    "requests>=2.31.0",    "pydantic>=2.0.0",][project.optional-dependencies]dev = [    "pytest>=7.4.0",    "pytest-cov>=4.1.0",    "black>=23.0.0",    "ruff>=0.1.0",    "mypy>=1.5.0",][tool.black]line-length = 88target-version = ['py39'][tool.ruff]line-length = 88select = ["E", "F", "I", "N", "W"][tool.mypy]python_version = "3.9"warn_return_any = truewarn_unused_configs = truedisallow_untyped_defs = true[tool.pytest.ini_options]testpaths = ["tests"]addopts = "--cov=mypackage --cov-report=term-missing"

快速参考:Python 惯用法

惯用法
描述
EAFP
请求宽恕比请求许可更容易
上下文管理器
使用 with 进行资源管理
列表推导式
用于简单的转换
生成器
用于惰性求值和大数据集
类型提示
注解函数签名
数据类
用于具有自动生成方法的数据容器
__slots__
用于内存优化
f-strings
用于字符串格式化 (Python 3.6+)
pathlib.Path
用于路径操作 (Python 3.4+)
enumerate
用于循环中的索引-元素对

应避免的反模式

# Bad: Mutable default argumentsdef append_to(item, items=[]):    items.append(item)    return items# Good: Use None and create new listdef append_to(item, items=None):    if items is None:        items = []    items.append(item)    return items# Bad: Checking type with type()if type(obj) == list:    process(obj)# Good: Use isinstanceif isinstance(obj, list):    process(obj)# Bad: Comparing to None with ==if value == None:    process()# Good: Use isif value is None:    process()# Bad: from module import *from os.path import *# Good: Explicit importsfrom os.path import join, exists# Bad: Bare excepttry:    risky_operation()except:    pass# Good: Specific exceptiontry:    risky_operation()except SpecificError as e:    logger.error(f"Operation failed: {e}")

记住:Python 代码应该具有可读性、显式性,并遵循最小意外原则。如有疑问,优先考虑清晰度而非巧妙性。

请在微信客户端打开

安装命令

npx skills add https://github.com/affaan-m/everything-claude-code --skill python-patterns

每周安装量:1.0K

代码仓库:https://github.com/affaan-m/everything-claude-code

GitHub 星标:70.6K

首次出现:2026年2月1日

安全审计:Gen Agent Trust HubPass SocketPass SnykPass

安装于:opencode859,codex849,gemini-cli812,github-copilot769,kimi-cli716,amp711

更多技能>>>

怎么安装AI Skills

find-skills 技能搜索工具 - 让AI更智能的skill

Skills之创业公司团队构成分析:种子轮到A轮招聘、薪酬与股权分配指南 GitHub Stars 35K+

Skills之OpenAI图像生成技能:AI绘图、图片编辑与批量生成,支持网站素材、UI设计、产品模型 GitHub Stars 1.7万+

Skills之Google Stitch UI设计提示指南:AI驱动UI生成工具使用技巧与最佳实践 GitHub Stars 3.5万+

Skills之Excel财务建模规范与xlsx文件处理指南:专业格式、零错误公式与数据分析 GitHub Stars 12万+

Skills之办公自动化工作流套件:LibreOffice与Microsoft Office文档创建、电子表格自动化、演示文稿生成与格式转换 GitHub Stars 3.5+

Skills之前端设计技能:从可用到惊艳的界面设计原则与工作流程 GitHub Stars 16.7万+

Skills之VSCode截图基线更新指南:从CI下载并提交组件截图基线 GitHub Stars 18万+

最新文章

随机文章