代码注释完善指南

版本: 1.0.0
更新日期: 2026-02-08

本文档提供代码注释和类型提示的完善指南,帮助开发者编写高质量的代码文档。


📚 目录

  1. 文档字符串规范
  2. 类型提示规范
  3. 示例代码
  4. 检查清单

文档字符串规范

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