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 项目官方文档,使用显式的 Parameters、Returns 等标题,格式更结构化,适合科学计算和数据分析项目。
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 : typeReturns描述返回值类型和含义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

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