Python 代码规范
本文档用于统一 Python 项目的代码风格、工具链和提交流程,降低协作成本并提升可维护性。
1. 代码组织
Section titled “1. 代码组织”1.1 模块设计
Section titled “1.1 模块设计”- 每个模块单一职责,避免一个文件承载过多功能
- 按功能拆分包,避免 util/common/misc 等万能包
- 功能相近的类型和函数放同一模块内
- 避免循环导入,内部实现用
_前缀标识私有
1.2 文件组织
Section titled “1.2 文件组织”- 文件内顺序:shebang → 编码声明 → 模块 docstring → import → 常量 → 变量 → 函数 → 类
- 一个文件专注一个核心类或功能组
#!/usr/bin/env python3# -*- coding: utf-8 -*-"""用户服务模块,提供用户相关的业务逻辑与数据访问。"""
from __future__ import annotations
import loggingfrom datetime import datetime
from pydantic import BaseModel
from .repository import UserRepository
MAX_RETRY_COUNT = 3
logger = logging.getLogger(__name__)
class User(BaseModel): id: int name: str
def get_user(user_id: int) -> User | None: ...2. 命名规范
Section titled “2. 命名规范”2.1 基本规则
Section titled “2.1 基本规则”- 模块/包:全小写短名,可用下划线分隔 (
user_service.py) - 类:PascalCase (
UserService,OrderProcessor) - 函数/方法/变量:snake_case (
get_user,item_count) - 常量:UPPER_SNAKE_CASE (
MAX_RETRY_COUNT,API_BASE_URL)
2.2 私有成员
Section titled “2.2 私有成员”- 非公开属性使用单下划线前缀 (
_internal_method,_cache) - 避免双下划线前缀,除非确实需要 name mangling 来避免子类冲突
2.3 布尔变量
Section titled “2.3 布尔变量”- 使用
is_/has_/can_前缀表示布尔含义
is_active: boolhas_permission: boolcan_edit: bool3. 类型标注
Section titled “3. 类型标注”3.1 基本要求
Section titled “3.1 基本要求”- 所有新增代码必须标注类型
- 公共接口必须提供完整函数签名标注
- Python 3.10+ 使用
X | None替代Optional[X] - Python 3.9+ 使用内建泛型
list[X]、dict[K, V],弃用typing.List、typing.Dict
3.2 复杂类型
Section titled “3.2 复杂类型”- 复杂结构优先使用
TypedDict、Protocol、dataclass - 避免大量
dict[str, Any],用结构化类型替代
from dataclasses import dataclassfrom typing import TypedDict
@dataclass(slots=True)class User: id: int name: str
class UserDict(TypedDict): id: int name: str
def find_user_name(users: list[User], user_id: int) -> str | None: for user in users: if user.id == user_id: return user.name return None3.3 类型检查
Section titled “3.3 类型检查”- 推荐使用 mypy
--strict模式
mypy --strict src/4. 导入规范
Section titled “4. 导入规范”4.1 导入顺序
Section titled “4.1 导入顺序”- 标准库 → 第三方库 → 本地模块,组间空行分隔
- 每个导入独占一行
import osimport sysfrom pathlib import Path
from pydantic import BaseModelfrom sqlalchemy import select
from .models import Userfrom .service import UserService4.2 禁止事项
Section titled “4.2 禁止事项”- 禁止
from module import *(__all__明确声明的公开模块除外) - 禁止循环导入
- 禁止相对路径导入
..跨越包边界
5. 字符串与格式化
Section titled “5. 字符串与格式化”5.1 字符串使用
Section titled “5.1 字符串使用”- 优先使用 f-string(Python 3.6+)
- 多行字符串用三引号
- 避免在循环中拼接字符串,使用
"".join()或StringIO
name = "Alice"msg = f"Hello, {name}!"
query = """ SELECT id, name FROM users WHERE active = true"""5.2 Docstring
Section titled “5.2 Docstring”- 模块、类、公共函数必须有 docstring
- 使用三引号,首行简述,空行后补充详细说明
- 推荐 Google 或 NumPy 风格
def get_user(user_id: int) -> User | None: """根据 ID 获取用户。
Args: user_id: 用户唯一标识符。
Returns: 匹配的 User 对象,未找到时返回 None。
Raises: ValueError: user_id 为非正整数时抛出。 """ if user_id <= 0: raise ValueError("user_id must be positive") ...6. 错误处理
Section titled “6. 错误处理”6.1 基本原则
Section titled “6.1 基本原则”- 捕获具体异常,禁止裸
except:或except Exception: - 自定义异常继承自
Exception,提供有意义的错误信息 - 禁止在 except 块中静默吞掉异常
6.2 异常设计
Section titled “6.2 异常设计”class UserNotFoundError(Exception): """用户不存在异常。"""
def __init__(self, user_id: int): self.user_id = user_id super().__init__(f"User {user_id} not found")
class ValidationError(Exception): """数据校验异常。""" ...6.3 资源管理
Section titled “6.3 资源管理”- 使用上下文管理器 (
with) 管理文件、连接等资源 - 自定义资源实现
__enter__和__exit__
with open("data.txt") as f: content = f.read()7. 函数与方法
Section titled “7. 函数与方法”7.1 函数设计
Section titled “7.1 函数设计”- 函数尽量小,推荐不超过 50 行
- 一个函数只做一件事
- 参数过多时考虑使用 dataclass 或 TypedDict 封装
7.2 默认参数
Section titled “7.2 默认参数”- 参数默认值使用不可变类型,禁止
def f(x=[])或def f(x={})
# 正确def append_item(item: str, items: list[str] | None = None) -> list[str]: if items is None: items = [] items.append(item) return items
# 错误def append_item(item: str, items: list[str] = []) -> list[str]: items.append(item) return items7.3 函数风格
Section titled “7.3 函数风格”- 使用关键字参数提高可读性
- 优先使用
def定义函数,禁止将 lambda 赋值给变量
# 正确def is_active(user: User) -> bool: return user.status == "active"
# 错误is_active = lambda user: user.status == "active"8. 类设计
Section titled “8. 类设计”8.1 设计原则
Section titled “8.1 设计原则”- 使用
@property而非 Java 风格的 getter/setter - 使用
@dataclass简化数据类 - 优先组合而非继承
- 多重继承时确保 MRO 清晰可理解
8.2 特殊方法
Section titled “8.2 特殊方法”__str__面向用户,返回可读性高的描述__repr__面向开发者,尽量返回可重建对象的表达式
from dataclasses import dataclass
@dataclass(slots=True)class User: id: int name: str email: str
@property def display_name(self) -> str: return self.name or self.email
def __str__(self) -> str: return f"User({self.display_name})"
def __repr__(self) -> str: return f"User(id={self.id!r}, name={self.name!r}, email={self.email!r})"9. 并发与异步
Section titled “9. 并发与异步”9.1 异步编程
Section titled “9.1 异步编程”- IO 密集型任务优先使用
async/await - 使用
asyncio.gather并发执行多个协程 - 使用
asyncio.to_thread包装同步阻塞调用
import asyncio
async def fetch_all(urls: list[str]) -> list[str]: async def fetch(url: str) -> str: ... return ""
return await asyncio.gather(*(fetch(url) for url in urls))9.2 线程安全
Section titled “9.2 线程安全”- 多线程场景使用
threading.Lock保护共享状态 - 使用
queue.Queue实现线程间通信 - 禁止在异步代码中使用
time.sleep,使用await asyncio.sleep
10. 测试规范
Section titled “10. 测试规范”10.1 框架与组织
Section titled “10.1 框架与组织”- 测试框架使用
pytest - 测试文件命名:
test_*.py,测试函数以test_开头 - 一个测试只验证一个主要行为
- 回归修复必须补充测试用例
10.2 测试实践
Section titled “10.2 测试实践”- 使用 fixtures 替代 setUp/tearDown
- 使用
pytest.mark.parametrize做参数化测试 - Mock 外部依赖,使用
unittest.mock或pytest-mock
import pytestfrom unittest.mock import Mock
from .service import UserService
@pytest.fixturedef user_service() -> UserService: repo = Mock() return UserService(repo)
def test_get_user_returns_none_when_not_found(user_service: UserService) -> None: user_service.repo.find_by_id.return_value = None assert user_service.get_user(1) is None
@pytest.mark.parametrize( ("user_id", "expected"), [(0, False), (-1, False), (1, True)],)def test_valid_user_id(user_id: int, expected: bool) -> None: assert is_valid_user_id(user_id) == expected11. 工具与格式化
Section titled “11. 工具与格式化”11.1 推荐工具链
Section titled “11.1 推荐工具链”- Python:
3.13+ - 包管理:
uv - 格式化与检查:
ruff - 类型检查:
ty或mypy - 测试:
pytest - 提交前钩子:
pre-commit
11.2 常用命令
Section titled “11.2 常用命令”ruff formatruff checkruff check --fixty checkpytestruff format负责代码格式化ruff check负责风格与常见问题检查--fix可自动修复部分问题- CI 中必须通过所有检查
12. 禁止事项
Section titled “12. 禁止事项”- 禁止裸
except:或except Exception: - 禁止使用可变默认参数 (
def f(x=[])) - 禁止在函数中修改全局变量
- 禁止硬编码密钥、凭证等敏感信息
- 禁止使用
assert做业务逻辑校验 - 禁止
from module import * - 禁止循环导入
- 禁止将 lambda 赋值给变量
- 禁止静默吞掉异常
- 禁止在异步代码中使用
time.sleep