文章目录

Python 文档字符串:docstring 格式与规范

发布于 2026-04-05 06:09:00 · 浏览 13 次 · 评论 0 条

Python 文档字符串:docstring 格式与规范


什么是 docstring

docstring 是 Python 函数、类、模块或方法定义中的第一个字符串表达式。它位于代码体的最开头位置,用于描述对象的用途和行为。与普通注释不同,docstring 会作为对象的 __doc__ 属性被保留下来,可通过 help() 函数或 obj.__doc__ 访问。

def calculate_area(radius):
    """计算圆的面积。

    Args:
        radius: 圆的半径,必须为正数

    Returns:
        圆的面积(浮点数)
    """
    import math
    return math.pi * radius ** 2

在上面的例子中,三引号包裹的多行字符串就是 docstring。调用 help(calculate_area) 时,这段描述会完整显示,这是 docstring 最核心的价值——为代码生成自文档。


单行与多行 docstring

单行 docstring

当功能足够简单、一句话就能说清楚时,使用单行 docstring。它必须是完整的句子,句末加上句号,且整体放在一行内。

class DataLoader:
    """用于加载和预处理数据集的通用加载器。"""

单行 docstring 的要点:

  • 保持简洁,一行概括核心功能
  • 句尾使用句号,保持一致性
  • 适用于功能简单、无需额外说明的场景

多行 docstring

复杂功能的 docstring 通常分为多个部分:首行描述对象用途,空白行分隔描述与参数说明,后续段落详细解释行为。

def fetch_data(url, timeout=30):
    """从指定 URL 获取数据。

    Args:
        url: 请求的目标地址,必须是有效的 HTTP/HTTPS 链接
        timeout: 超时时间(秒),默认为 30 秒

    Returns:
        response: requests 库的 Response 对象

    Raises:
        ConnectionError: 网络连接失败时抛出
        TimeoutError: 请求超时时抛出
    """
    import requests
    response = requests.get(url, timeout=timeout)
    response.raise_for_status()
    return response

主流 docstring 风格

Python 社区发展出多种 docstring 规范,其中 Google 风格、NumPy 风格和 Sphinx 风格最为流行。选择一种风格并坚持使用,比选择哪种风格更重要

Google 风格

Google 风格是初学者最容易掌握的格式,使用简洁的英文标签标注各部分信息,不依赖复杂的标记语法。

class CacheManager:
    """内存缓存管理器,支持过期策略和LRU淘汰。"""

    def __init__(self, max_size=1000, ttl=3600):
        """初始化缓存管理器。

        Args:
            max_size: 最大缓存条目数,超出后自动淘汰最久未使用项
            ttl: 存活时间(秒),过期条目自动失效
        """
        self._cache = {}
        self._max_size = max_size
        self._ttl = ttl
        self._access_order = []

    def get(self, key):
        """获取缓存值。

        Args:
            key: 缓存键

        Returns:
            缓存值,若不存在或已过期则返回 None
        """
        if key not in self._cache:
            return None
        import time
        if time.time() - self._cache[key]['time'] > self._ttl:
            del self._cache[key]
            return None
        self._access_order.remove(key)
        self._access_order.append(key)
        return self._cache[key]['value']

    def set(self, key, value):
        """设置缓存键值对。

        Args:
            key: 缓存键
            value: 要缓存的值
        """
        if key in self._cache:
            self._access_order.remove(key)
        self._access_order.append(key)
        if len(self._access_order) > self._max_size:
            removed_key = self._access_order.pop(0)
            del self._cache[removed_key]
        self._cache[key] = {'value': value, 'time': __import__('time').time()}

Google 风格的常用标签:

标签 用途 示例
Args: 参数说明 name: 用户姓名,字符串类型
Returns: 返回值说明 bool: 操作是否成功
Raises: 可能的异常 ValueError: 参数无效时抛出
Attributes: 类属性说明 count: 当前实例计数器
Examples: 使用示例 展示调用方法

NumPy 风格

NumPy 风格源自 NumPy 项目官方文档,使用显式的 ParametersReturns 等标题,格式更结构化,适合科学计算和数据分析项目。

def matrix_multiply(A, B):
    """执行两个矩阵的矩阵乘法运算。

    Parameters
    ----------
    A : ndarray, shape (M, N)
        左侧输入矩阵,维度为 M x N
    B : ndarray, shape (N, K)
        右侧输入矩阵,维度为 N x K

    Returns
    -------
    C : ndarray, shape (M, K)
        矩阵乘积结果,维度为 M x K

    Raises
    ------
    ValueError
        当矩阵维度不匹配,无法相乘时抛出

    Notes
    -----
    该实现使用三重循环,对于大型矩阵性能较差。
    生产环境建议使用 NumPy 的内置矩阵乘法:
    `np.dot(A, B)` 或 `A @ B`
    """
    import numpy as np
    A = np.asarray(A)
    B = np.asarray(B)
    if A.shape[1] != B.shape[0]:
        raise ValueError(
            f"矩阵维度不匹配: A 的列数 ({A.shape[1]}) "
            f"不等于 B 的行数 ({B.shape[0]})"
        )
    M, K = A.shape[0], B.shape[1]
    C = np.zeros((M, K), dtype=A.dtype)
    for i in range(M):
        for j in range(K):
            for k in range(A.shape[1]):
                C[i, j] += A[i, k] * B[k, j]
    return C

NumPy 风格的标题格式:

  • Parameters 后接参数列表,每个参数格式为 name : type
  • Returns 描述返回值类型和含义
  • Raises 列出可能抛出的异常
  • Notes 补充使用说明和注意事项

Sphinx 风格

Sphinx 是 Python 官方文档生成工具,它使用 reStructuredText(RST)标记,格式更复杂但功能强大,支持自动链接、代码示例语法高亮等高级特性。

class APIClient:
    """REST API 客户端,用于与远程服务通信。

    :ivar str base_url: API 的基础 URL 地址
    :ivar dict headers: 请求时携带的 HTTP 头信息
    :ivar float timeout: 请求超时时间(秒)
    """

    def __init__(self, base_url, api_key=None, timeout=30.0):
        """初始化 API 客户端。

        :param str base_url: API 的根地址,如 ``https://api.example.com/v1``
        :param str api_key: 认证密钥,默认为 None 表示无需认证
        :param float timeout: 单次请求的超时时间,默认 30 秒
        """
        self.base_url = base_url.rstrip('/')
        self.headers = {'Content-Type': 'application/json'}
        if api_key:
            self.headers['Authorization'] = f'Bearer {api_key}'
        self.timeout = timeout

    def get(self, endpoint, params=None):
        """发送 GET 请求。

        :param str endpoint: API 端点路径,相对于 base_url
        :param dict params: URL 查询参数
        :return: JSON 解析后的响应数据
        :rtype: dict 或 list

        :raises ConnectionError: 网络连接失败
        :raises TimeoutError: 请求超时

        Example:
            >>> client = APIClient('https://api.example.com', 'secret-key')
            >>> result = client.get('/users', params={'page': 1})
            >>> print(result['data'])
        """
        import requests
        url = f'{self.base_url}/{endpoint.lstrip("/")}'
        response = requests.get(
            url, 
            params=params, 
            headers=self.headers, 
            timeout=self.timeout
        )
        response.raise_for_status()
        return response.json()

各风格对比与选择

特性 Google 风格 NumPy 风格 Sphinx 风格
可读性 高,易于编写 高,结构清晰 中,需学习 RST 语法
自动文档工具 支持(需插件) 原生支持 原生支持
学习成本
适用场景 通用项目、API 文档 科学计算、数据分析 库开发、官方文档

选择建议:

  • 小型项目或团队协作:优先选择 Google 风格,学习成本低,可读性好
  • 数据科学/机器学习项目:选择 NumPy 风格,与 NumPy、SciPy 生态保持一致
  • 开源库/框架开发:选择 Sphinx 风格,文档生成最专业

特殊场景的 docstring 写法

抽象方法的 docstring

抽象基类中的方法应明确说明子类必须实现的行为。

from abc import ABC, abstractmethod

class Renderer(ABC):
    """图形渲染器的抽象基类。"""

    @abstractmethod
    def draw(self, shape):
        """绘制给定的图形对象。

        Args:
            shape: 要绘制的图形对象,具体类型由子类决定

        Raises:
            NotImplementedError: 子类未实现此方法时抛出
        """
        pass

上下文管理器的 docstring

class Timer:
    """上下文管理器,用于测量代码块执行时间。"""

    def __enter__(self):
        """进入上下文时记录开始时间。

        Returns:
            self: 返回当前实例用于精确计时
        """
        import time
        self._start = time.perf_counter()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """退出上下文时计算并打印耗时。

        Args:
            exc_type: 异常类型(如果有)
            exc_val: 异常值(如果有)
            exc_tb: 异常回溯(如果有)

        Returns:
            False: 不抑制异常传播
        """
        import time
        self._elapsed = time.perf_counter() - self._start
        print(f'执行时间: {self._elapsed:.4f} 秒')
        return False

属性的 docstring

使用属性装饰器时,docstring 写在 getter 方法内部。

class Rectangle:
    """矩形类,支持面积和周长计算。"""

    def __init__(self, width, height):
        self._width = width
        self._height = height

    @property
    def width(self):
        """float: 矩形的宽度,必须为非负数。"""
        return self._width

    @width.setter
    def width(self, value):
        if value < 0:
            raise ValueError('宽度不能为负数')
        self._width = value

使用 docstring 生成文档

通过 help() 函数查看

直接查看函数的帮助信息,验证 docstring 是否正确编写。

def add(a, b):
    """返回两个数的和。

    Args:
        a: 第一个加数
        b: 第二个加数

    Returns:
        a 和 b 的和
    """
    return a + b

# 在交互式环境或脚本中运行
print(help(add))

使用 Sphinx 生成 HTML 文档

安装 Sphinx 并初始化项目目录后运行:

pip install sphinx
sphinx-quickstart docs

配置 docs/source/conf.py 中的 extensions

extensions = ['sphinx.ext.autodoc']

运行文档生成命令:

cd docs
make html

生成的 HTML 文档会从 docstring 中提取所有说明信息,自动生成美观的文档页面。

使用 pydoc 命令行工具

Python 内置的 pydoc 工具可以直接在终端查看模块文档:

python -m pydoc your_module_name

导出为 HTML 文件:

python -m pydoc -w your_module_name

最佳实践总结

必须遵守的规范:

  • 使用三引号定义 docstring,即使单行也要用三引号
  • 多行 docstring 首行后必须有空行
  • 参数名、类型、返回值必须描述完整
  • 保持时态一致,推荐使用第三人称描述

应当避免的做法:

# 错误示例:缺少参数说明
def process(data):
    """处理数据。"""
    pass

# 错误示例:类型信息不明确
def login(user, password):
    """用户登录。

    Args:
        user: 用户信息
        password: 密码
    """
    pass

# 正确写法
def login(username, password):
    """用户登录验证。

    Args:
        username: 登录用户名,字符串类型
        password: 登录密码,字符串类型

    Returns:
        bool: 登录成功返回 True,失败返回 False

    Raises:
        AuthenticationError: 密码错误时抛出
        AccountLockedError: 账户被锁定时抛出
    """
    pass

提升可读性的技巧:

  • 在Args部分使用“必须”“可选”等词汇明确参数的约束条件
  • 为复杂的字典参数提供结构示例
  • 为枚举类型的参数列出所有可选值
  • 为可能为空返回值的函数明确说明何时返回 None

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文