不使用类型提示
错误:Python 是动态类型,不需要类型提示 正确:类型提示提高可读性和 IDE 支持
来源: everything-claude-code 技能库
python-patterns 涵盖 Pythonic 惯用语、PEP 8 标准、类型提示和构建健壮、高效、可维护应用的最佳实践。
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]避免魔法;要清楚代码做什么:
# 好:显式配置import logging
logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 不好:隐藏的副作用import some_modulesome_module.setup() # 这是做什么的?Python 更喜欢异常处理而非条件检查:
# 好:EAFP 风格def get_value(dictionary: dict, key: str) -> Any: try: return dictionary[key] except KeyError: return None
# 不好:LBYL 风格def get_value(dictionary: dict, key: str) -> Any: if key in dictionary: return dictionary[key] return None优先使用组合而非继承:
# 好:组合class Logger: def log(self, message): print(message)
class UserService: def __init__(self, logger: Logger): self.logger = logger
def create_user(self, name): self.logger.log(f"Creating user: {name}")
# 不好:过度继承class UserServiceWithLogging(UserService): # 继承所有方法,可能不需要 pass类型提示让代码更清晰,IDE 支持更好:
# 变量类型name: str = "张三"age: int = 25prices: list[float] = [1.5, 2.0, 3.5]user_dict: dict[str, User] = {}
# 函数类型提示def greet(name: str) -> str: return f"Hello, {name}!"
def process_items(items: list[int]) -> dict[str, int]: return { "sum": sum(items), "count": len(items), "avg": sum(items) / len(items) }from typing import Optional, Union, Callable, TypeVar, Generic
# Optional - 可能为 Nonedef find_user(user_id: int) -> Optional[User]: # 可能返回 User 或 None pass
# Union - 多种类型def process_input(value: Union[str, int]) -> str: return str(value)
# Callable - 可调用对象def apply_function(func: Callable[[int], int], value: int) -> int: return func(value)
# TypeVar - 泛型T = TypeVar('T')
def first_element(items: list[T]) -> Optional[T]: return items[0] if items else Nonefrom dataclasses import dataclassfrom pydantic import BaseModel
# dataclass - 简单数据容器@dataclassclass User: name: str email: str age: int = 0 # 默认值
# Pydantic - 数据验证class UserModel(BaseModel): name: str email: str age: int = 0
@validator('email') def email_must_be_valid(cls, v): if '@' not in v: raise ValueError('Invalid email') return v# 类方式class FileManager: def __init__(self, filename: str): self.filename = filename
def __enter__(self): self.file = open(self.filename, 'r') return self.file
def __exit__(self, exc_type, exc_val, exc_tb): if self.file: self.file.close()
# 函数方式(推荐)from contextlib import contextmanager
@contextmanagerdef managed_resource(): resource = acquire_resource() try: yield resource finally: release_resource(resource)
# 使用with managed_resource() as resource: # 使用资源 passclass Counter: def __init__(self, limit: int): self.limit = limit self.current = 0
def __iter__(self): return self
def __next__(self): if self.current >= self.limit: raise StopIteration self.current += 1 return self.current
# 使用生成器def count_to(limit: int): current = 1 while current <= limit: yield current current += 1# 方式 1:模块级单例class _Config: value = None
config = _Config()
# 方式 2:装饰器def singleton(cls): instances = {} def get_instance(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return get_instance
@singletonclass Database: passclass Subject: def __init__(self): self._observers = []
def attach(self, observer): self._observers.append(observer)
def detach(self, observer): self._observers.remove(observer)
def notify(self, *args, **kwargs): for observer in self._observers: observer.update(*args, **kwargs)
class Observer: def update(self, message): print(f"Received: {message}")✅ 正确做法:1. 使用列表推导式2. 使用类型提示3. 遵循 PEP 84. 编写 docstring
❌ 错误做法:1. 使用传统 for 循环2. 省略类型提示3. 忽略代码风格4. 不写文档✅ 正确做法:1. 使用 EAFP 风格2. 只捕获特定异常3. 记录异常信息4. 清理资源(finally 或 context manager)
❌ 错误做法:1. 捕获所有异常 (except:)2. 忽略异常信息3. 不释放资源✅ 正确做法:1. 为函数添加返回类型2. 为公共 API 添加类型3. 使用 Optional 处理 None4. 使用 Union 处理多种类型
❌ 错误做法:1. 完全不使用类型提示2. 使用 any 类型3. 类型提示与实现不一致# 代码检查ruff check .pylint .flake8 .
# 代码格式化black .ruff format .
# 类型检查mypy .pyright .
# 运行测试pytest
# 代码质量pylint --rcfile=pylintrc mymodule.py不使用类型提示
错误:Python 是动态类型,不需要类型提示 正确:类型提示提高可读性和 IDE 支持
过度使用异常
错误:用异常处理控制流程 正确:异常只用于异常情况
忽略 PEP 8
错误:代码能跑就行 正确:遵循代码风格指南
使用可变默认值
错误:def f(a=[]): … 正确:def f(a=None): if a is None: a = []
何时使用
何时不用
关键要点
常见错误
Pythonic 不仅仅是语法技巧,而是一种思维方式:
| 技能 | 关系 |
|---|---|
| python-testing | 测试驱动开发 |
| code-review | 代码审查 |
| tdd-workflow | TDD 工作流 |
pip install ruff mypy blackruff check . && mypy .ruff format .官方原文: python-patterns SKILL.md
💡 提示:代码是写给人看的,顺便能在机器上运行。