代码注释完善指南
版本: 1.0.0
更新日期: 2026-02-08
本文档提供代码注释和类型提示的完善指南,帮助开发者编写高质量的代码文档。
📚 目录
文档字符串规范
1. 函数文档字符串格式
使用 Google 风格的文档字符串:
def function_name(param1: Type1, param2: Type2) -> ReturnType:
"""
函数简短描述(一行)
详细描述(可选,多行)
可以包含更多信息,如使用场景、注意事项等。
Args:
param1: 参数1的详细说明
param2: 参数2的详细说明,包含类型和约束
Returns:
返回值的详细说明,包括类型和含义
Raises:
ValueError: 当参数无效时抛出
HTTPException: 当请求失败时抛出(状态码: 400)
Example:
>>> result = function_name("value1", "value2")
>>> print(result)
"result_value"
Note:
特殊注意事项或实现细节
See Also:
相关函数或文档的引用
"""
pass
2. 类文档字符串格式
class ClassName:
"""
类的简短描述
详细描述类的用途、主要功能和使用场景。
Attributes:
attr1: 属性1的说明
attr2: 属性2的说明
Example:
>>> obj = ClassName()
>>> obj.method()
"result"
Note:
类的特殊说明
"""
def __init__(self, param: Type):
"""
初始化类实例
Args:
param: 初始化参数的说明
"""
pass
3. 模块文档字符串格式
"""
模块名称
模块的简短描述,说明模块的主要功能和用途。
主要功能:
- 功能1:描述
- 功能2:描述
- 功能3:描述
使用示例:
from module import ClassName
obj = ClassName()
result = obj.method()
数据存储:
- PostgreSQL: 持久化数据
- Redis: 缓存数据
线程安全:
- 所有操作都是异步的
- 使用异步锁保护共享资源
注意:
- 重要注意事项
- 已知限制
版本历史:
- v1.0.0 (2026-02-08): 初始版本
"""
类型提示规范
1. 基本类型提示
from typing import Optional, List, Dict, Any, Union, Tuple
# 基本类型
def func1(name: str, age: int, is_active: bool) -> str:
"""基本类型提示"""
return f"{name} is {age} years old"
# 可选类型
def func2(value: Optional[str] = None) -> Optional[int]:
"""可选类型"""
return len(value) if value else None
# 列表和字典
def func3(items: List[str], config: Dict[str, Any]) -> List[Dict[str, str]]:
"""集合类型"""
return [{"key": item} for item in items]
# 联合类型
def func4(value: Union[int, str]) -> Union[int, str]:
"""联合类型"""
return value
# 元组
def func5() -> Tuple[str, int, bool]:
"""返回元组"""
return ("name", 42, True)
2. 异步函数类型提示
from typing import Awaitable, Coroutine
from uuid import UUID
async def async_func(user_id: UUID) -> Dict[str, Any]:
"""
异步函数类型提示
Args:
user_id: 用户ID
Returns:
包含用户信息的字典
"""
return {"user_id": str(user_id)}
3. 复杂类型提示
from typing import Callable, TypeVar, Generic, Protocol
from pydantic import BaseModel
# 泛型
T = TypeVar('T')
class Container(Generic[T]):
"""泛型容器"""
def __init__(self, value: T):
self.value = value
# 回调函数
def process_data(
data: List[str],
callback: Callable[[str], bool]
) -> List[str]:
"""使用回调函数"""
return [item for item in data if callback(item)]
# Protocol(接口)
class Processor(Protocol):
"""处理器协议"""
def process(self, data: str) -> str:
"""处理数据"""
...
# Pydantic 模型
class UserModel(BaseModel):
"""用户模型"""
id: UUID
name: str
email: Optional[str] = None
4. FastAPI 路由类型提示
from fastapi import APIRouter, Depends, HTTPException
from uuid import UUID
from pydantic import BaseModel
router = APIRouter()
class RequestModel(BaseModel):
"""请求模型"""
field1: str
field2: Optional[int] = None
class ResponseModel(BaseModel):
"""响应模型"""
success: bool
data: Dict[str, Any]
@router.post("/endpoint", response_model=ResponseModel)
async def endpoint_handler(
data: RequestModel,
user_id: UUID = Depends(get_current_user)
) -> ResponseModel:
"""
端点处理函数
Args:
data: 请求数据
user_id: 当前用户ID(从认证依赖获取)
Returns:
响应数据
Raises:
HTTPException: 当操作失败时抛出(状态码: 400)
"""
# 实现逻辑
return ResponseModel(success=True, data={})
示例代码
示例 1: 完整的函数文档
from typing import Optional, List, Dict, Any
from uuid import UUID
from datetime import datetime
from fastapi import HTTPException
async def get_user_balance(
user_id: UUID,
include_history: bool = False
) -> Dict[str, Any]:
"""
获取用户 Token 余额
从数据库查询用户的 Token 余额信息,包括配额、已使用量、剩余额度等。
支持 Redis 缓存以提高性能(TTL: 5分钟)。
Args:
user_id: 用户ID(UUID格式)
include_history: 是否包含历史记录,默认为 False
Returns:
包含以下字段的字典:
- user_id: 用户ID(字符串)
- plan_code: 套餐代码(如 "free", "pro")
- plan_name: 套餐名称(如 "免费版", "专业版")
- monthly_quota: 月度配额(-1表示无限)
- used_this_month: 本月已使用量
- remaining: 剩余额度
- usage_percent: 使用百分比(0-100)
- overage_tokens: 超量使用的 Token 数
- overage_cost_cents: 超量费用(分)
- allow_overage: 是否允许超量使用
Raises:
HTTPException: 当用户不存在时抛出(状态码: 404)
Example:
>>> from uuid import uuid4
>>> user_id = uuid4()
>>> balance = await get_user_balance(user_id)
>>> print(balance["remaining"])
50000
Note:
- 如果用户没有订阅,返回免费套餐的默认值
- 缓存会在余额变更时自动失效
- 每月1日自动重置使用量
See Also:
- record_usage: 记录 Token 使用量
- upgrade_subscription: 升级订阅套餐
"""
# 实现代码
pass
示例 2: 完整的类文档
from typing import Optional, Dict, Any, List
from uuid import UUID
from datetime import datetime
from loguru import logger
class TokenBillingService:
"""
Token 计费服务
统一管理用户的 Token 额度、使用记录和计费逻辑。
支持套餐管理、超量计费、月度重置等功能。
Attributes:
WARNING_THRESHOLDS: 余额预警阈值列表 [0.8, 0.9, 1.0]
_BALANCE_CACHE_TTL: 余额缓存过期时间(秒),默认 300
Example:
>>> service = TokenBillingService()
>>> balance = await service.get_user_balance(user_id)
>>> result = await service.record_usage(user_id, 100, 50)
Thread Safety:
所有方法都是异步的,支持并发调用。
使用数据库事务保证数据一致性。
Note:
- 使用 Redis 缓存提高查询性能
- 超量计费仅在 allow_overage=True 时生效
- 每月1日自动重置使用量
"""
WARNING_THRESHOLDS = [0.8, 0.9, 1.0]
async def get_user_balance(self, user_id: UUID) -> Dict[str, Any]:
"""
获取用户 Token 余额(带缓存)
优先从 Redis 缓存读取,缓存未命中时查询数据库。
缓存 TTL 为 5 分钟,余额变更时会主动失效缓存。
Args:
user_id: 用户ID
Returns:
余额信息字典,包含配额、使用量、剩余额度等
Raises:
ValueError: 当 user_id 无效时抛出
"""
pass
async def record_usage(
self,
user_id: UUID,
tokens_in: int,
tokens_out: int,
action_type: str = "chat",
session_id: Optional[str] = None,
model: Optional[str] = None,
endpoint: Optional[str] = None,
) -> Dict[str, Any]:
"""
记录 Token 使用量
更新用户的 Token 使用记录,计算超量费用,并检查配额限制。
Args:
user_id: 用户ID
tokens_in: 输入 Token 数量
tokens_out: 输出 Token 数量
action_type: 操作类型,如 "chat", "analyze", "route",默认为 "chat"
session_id: 会话ID(可选)
model: 使用的模型名称(可选)
endpoint: API 端点(可选)
Returns:
包含以下字段的字典:
- success: 是否成功(bool)
- remaining: 剩余额度(int,-1表示无限)
- warning: 预警消息(可选)
- error: 错误消息(可选)
- overage_cost: 超量费用(分)
Raises:
ValueError: 当参数无效时抛出
HTTPException: 当配额不足时抛出(状态码: 403)
Example:
>>> result = await service.record_usage(
... user_id=user_id,
... tokens_in=100,
... tokens_out=50,
... action_type="chat"
... )
>>> if result["success"]:
... print(f"剩余额度: {result['remaining']}")
"""
pass
示例 3: FastAPI 路由文档
from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel, EmailStr
from uuid import UUID
from typing import Optional
router = APIRouter()
class UserCreate(BaseModel):
"""用户创建请求模型"""
email: EmailStr
password: str
username: Optional[str] = None
phone: Optional[str] = None
class UserResponse(BaseModel):
"""用户响应模型"""
user_id: str
email: str
username: Optional[str]
created_at: datetime
@router.post("/register", response_model=Dict[str, str])
async def register_user(
data: UserCreate,
background_tasks: BackgroundTasks
) -> Dict[str, str]:
"""
用户注册
创建新用户账户,支持多种注册方式:
- 邮箱+密码(标准注册)
- 手机号+密码
- 设备ID自动注册(小智设备等)
注册成功后会自动创建免费订阅,并发送欢迎邮件。
Args:
data: 用户创建数据,包含邮箱、密码等信息
background_tasks: FastAPI 后台任务,用于异步处理注册后任务
Returns:
包含以下字段的字典:
- message: 注册结果消息("注册成功" 或 "设备已注册")
- user_id: 用户ID(UUID字符串)
- access_token: 访问令牌(JWT)
- refresh_token: 刷新令牌(JWT)
- token_type: Token类型(固定为 "bearer")
Raises:
HTTPException:
- 400: 邮箱已注册或参数无效
- 422: 缺少必需参数(邮箱或设备ID)
Example:
>>> data = UserCreate(
... email="user@example.com",
... password="SecurePassword123!",
... username="testuser"
... )
>>> result = await register_user(data, background_tasks)
>>> print(result["user_id"])
"550e8400-e29b-41d4-a716-446655440000"
Note:
- 密码会自动进行 bcrypt 哈希处理
- 如果设备已注册,会直接返回登录 Token
- 注册后任务(如发送邮件)在后台异步执行
See Also:
- login: 用户登录
- refresh_token: 刷新访问令牌
"""
# 实现代码
pass
检查清单
函数文档检查清单
函数签名
- 所有参数都有类型提示
- 返回值有类型提示
- 可选参数有默认值
文档字符串
- 有简短描述(一行)
- 有详细描述(如需要)
- 所有参数都有说明(Args)
- 返回值有说明(Returns)
- 异常有说明(Raises)
- 有使用示例(Example)
- 有注意事项(Note,如需要)
代码质量
- 函数名清晰表达意图
- 参数名清晰
- 没有硬编码值
- 错误处理完善
类文档检查清单
类签名
- 类有文档字符串
- 所有公共方法都有类型提示
- 所有公共属性都有类型提示
文档字符串
- 有类的简短描述
- 有详细描述和使用场景
- 列出了主要属性(Attributes)
- 有使用示例(Example)
- 有线程安全说明(如适用)
方法文档
- 所有公共方法都有文档字符串
-
__init__方法有完整文档 - 特殊方法(
__str__,__repr__等)有文档
模块文档检查清单
模块文档字符串
- 有模块简短描述
- 列出了主要功能
- 有使用示例
- 说明了数据存储方式
- 说明了线程安全性
- 列出了注意事项
导入和导出
- 使用
__all__明确导出 - 导入语句清晰有序
- 避免循环导入
- 使用
工具和自动化
1. 使用 mypy 进行类型检查
# 安装 mypy
pip install mypy
# 检查类型
mypy src/
# 配置文件: pyproject.toml
[tool.mypy]
python_version = "3.8"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
2. 使用 pydocstyle 检查文档字符串
# 安装 pydocstyle
pip install pydocstyle
# 检查文档字符串
pydocstyle src/
# 配置文件: .pydocstyle
[pydocstyle]
convention = google
3. 使用 sphinx 生成文档
# 安装 sphinx
pip install sphinx sphinx-rtd-theme
# 生成文档
sphinx-build -b html docs/ docs/_build/
最佳实践
1. 优先完善公共 API
- ✅ 优先为公共 API 添加完整文档
- ✅ 优先为接口和协议添加文档
- ✅ 优先为关键业务逻辑添加文档
2. 保持文档与代码同步
- ✅ 代码变更时同步更新文档
- ✅ 使用类型提示减少文档维护成本
- ✅ 定期审查文档准确性
3. 使用类型提示减少文档负担
# ✅ 好的做法:类型提示清晰,文档简洁
def process_user(user_id: UUID, include_stats: bool = False) -> UserResponse:
"""处理用户数据"""
pass
# ❌ 不好的做法:缺少类型提示,需要详细文档说明类型
def process_user(user_id, include_stats=False):
"""
处理用户数据
Args:
user_id: 用户ID,必须是有效的UUID格式字符串
include_stats: 是否包含统计信息,布尔值,默认为False
Returns:
用户响应对象,包含用户基本信息和可选的统计信息
"""
pass
4. 文档字符串应该回答的问题
- 做什么:函数/类的用途
- 为什么:为什么需要这个功能
- 如何使用:提供使用示例
- 注意事项:重要的限制或警告
- 相关功能:指向相关函数或文档
相关资源
文档版本: 1.0.0
最后更新: 2026-02-08