PEP 257 – 文档字符串约定
- 作者:
- David Goodger <goodger at python.org>,Guido van Rossum <guido at python.org>
- 讨论列表:
- Doc-SIG 列表
- 状态:
- 活跃
- 类型:
- 信息性
- 创建日期:
- 2001年5月29日
- 修订历史:
- 2001年6月13日
摘要
本 PEP 文档记录了与 Python 文档字符串相关的语义和约定。
基本原理
本 PEP 的目标是标准化文档字符串的高级结构:它们应该包含什么内容,以及如何表达(不涉及文档字符串中的任何标记语法)。PEP 包含约定,而不是法律或语法。
“一个通用的约定提供了所有可维护性、清晰度、一致性和良好编程习惯的基础。它不会强迫你违背自己的意愿遵循它。这就是 Python!”——Tim Peters 在 comp.lang.python 上,2001-06-16
如果你违反了这些约定,最糟糕的结果就是一些异样的眼光。但是一些软件(例如 Docutils 文档字符串处理系统 PEP 256,PEP 258)会了解这些约定,所以遵循它们会让你获得最佳结果。
规范
什么是文档字符串?
文档字符串是在模块、函数、类或方法定义中作为第一个语句出现的字符串字面量。这样的文档字符串成为该对象的 __doc__
特殊属性。
所有模块通常都应该有文档字符串,并且模块导出的所有函数和类也应该有文档字符串。公共方法(包括 __init__
构造函数)也应该有文档字符串。包可以在包目录中 __init__.py
文件的模块文档字符串中进行文档化。
Python 代码中其他地方出现的字符串字面量也可能充当文档。它们不被 Python 字节码编译器识别,也不能作为运行时对象属性访问(即未分配给 __doc__
),但两种类型的额外文档字符串可以由软件工具提取
- 在模块、类或
__init__
方法的顶层,紧跟在简单赋值语句后的字符串字面量称为“属性文档字符串”。 - 紧跟在另一个文档字符串后的字符串字面量称为“附加文档字符串”。
请参阅 PEP 258,“Docutils 设计规范”,以获取有关属性和附加文档字符串的详细说明。
为了保持一致性,始终使用 """三重双引号"""
括起文档字符串。如果您在文档字符串中使用了任何反斜杠,请使用 r"""原始三重双引号"""
。
文档字符串有两种形式:单行和多行。
单行文档字符串
单行文档字符串用于非常明显的情况。它们确实应该在一行内。例如
def kos_root():
"""Return the pathname of the KOS root directory."""
global _kos_root
if _kos_root: return _kos_root
...
注释
- 即使字符串适合在一行内,也使用三重引号。这使得以后扩展它变得容易。
- 结束引号与开始引号在同一行。这使得单行文档字符串看起来更好。
- 文档字符串前后都没有空行。
- 文档字符串是一个以句点结尾的短语。它规定了函数或方法的效果,如同命令(“执行此操作”,“返回那个”),而不是描述;例如,不要写“返回路径名…”。
- 单行文档字符串不应该是重复函数/方法参数的“签名”(可以通过内省获取)。不要这样做
def function(a, b): """function(a, b) -> list"""
这种类型的文档字符串仅适用于 C 函数(例如内置函数),在这些函数中,内省是不可能的。但是,返回值的性质无法通过内省确定,因此应该提及。这种文档字符串的首选形式应该是类似于
def function(a, b): """Do X and return a list."""
(当然,“执行 X”应该替换为有用的描述!)
多行文档字符串
多行文档字符串由一个类似于单行文档字符串的摘要行组成,后跟一个空行,然后是一个更详细的描述。摘要行可供自动索引工具使用;重要的是,它必须适合一行,并且与文档字符串的其余部分之间用空行隔开。摘要行可以与开始引号在同一行,也可以在下一行。整个文档字符串的缩进与第一行的引号相同(参见下面的示例)。
在所有记录类的文档字符串(单行或多行)之后插入一个空行——一般来说,类的每个方法之间用一个空行隔开,文档字符串需要用一个空行与第一个方法隔开。
脚本(独立程序)的文档字符串应该可以用作其“用法”消息,当脚本以不正确或缺少参数(或者可能使用“-h”选项表示“帮助”)调用时打印。这样的文档字符串应该记录脚本的功能和命令行语法、环境变量以及文件。用法消息可以相当详细(几屏内容),应该足以让新用户正确使用该命令,以及为高级用户提供所有选项和参数的完整快速参考。
模块的文档字符串通常应该列出模块导出的类、异常和函数(以及任何其他对象),并提供每个对象的单行摘要。(这些摘要通常提供的细节少于对象文档字符串中的摘要行。)包的文档字符串(即包的 __init__.py
模块的文档字符串)也应该列出包导出的模块和子包。
函数或方法的文档字符串应该总结其行为并记录其参数、返回值、副作用、引发的异常以及何时可以调用它的限制(所有适用的内容)。应指示可选参数。应该记录关键字参数是否属于接口的一部分。
类的文档字符串应该总结其行为并列出公共方法和实例变量。如果该类旨在被子类化,并且具有用于子类的附加接口,则应单独列出此接口(在文档字符串中)。类构造函数应在其 __init__
方法的文档字符串中进行记录。各个方法应由其自己的文档字符串进行记录。
如果一个类是另一个类的子类,并且其行为主要继承自该类,则其文档字符串应该提及这一点并总结差异。使用动词“覆盖”表示子类方法替换超类方法并且不调用超类方法;使用动词“扩展”表示子类方法调用超类方法(除了它自己的行为之外)。
不要使用 Emacs 的约定,在运行文本中用大写字母提及函数或方法的参数。Python 区分大小写,参数名称可用于关键字参数,因此文档字符串应记录正确的参数名称。最好在单独的行上列出每个参数。例如
def complex(real=0.0, imag=0.0):
"""Form a complex number.
Keyword arguments:
real -- the real part (default 0.0)
imag -- the imaginary part (default 0.0)
"""
if imag == 0.0 and real == 0.0:
return complex_zero
...
除非整个文档字符串适合一行,否则将结束引号放在单独的一行上。这样,Emacs 的 fill-paragraph
命令就可以用在它上面。
处理文档字符串缩进
文档字符串处理工具将从文档字符串的第二行及后续行中剥离统一数量的缩进,该缩进等于第一行后所有非空行的最小缩进。文档字符串第一行中的任何缩进(即直到第一个换行符)都是无关紧要的,并且会被删除。文档字符串中后续行的相对缩进将保留。应从文档字符串的开头和结尾删除空行。
由于代码比文字更精确,因此这里有一个算法的实现
def trim(docstring):
if not docstring:
return ''
# Convert tabs to spaces (following the normal Python rules)
# and split into a list of lines:
lines = docstring.expandtabs().splitlines()
# Determine minimum indentation (first line doesn't count):
indent = sys.maxsize
for line in lines[1:]:
stripped = line.lstrip()
if stripped:
indent = min(indent, len(line) - len(stripped))
# Remove indentation (first line is special):
trimmed = [lines[0].strip()]
if indent < sys.maxsize:
for line in lines[1:]:
trimmed.append(line[indent:].rstrip())
# Strip off trailing and leading blank lines:
while trimmed and not trimmed[-1]:
trimmed.pop()
while trimmed and not trimmed[0]:
trimmed.pop(0)
# Return a single string:
return '\n'.join(trimmed)
此示例中的文档字符串包含两个换行符,因此有 3 行长。第一行和最后一行是空白行
def foo():
"""
This is the second line of the docstring.
"""
为了说明
>>> print repr(foo.__doc__)
'\n This is the second line of the docstring.\n '
>>> foo.__doc__.splitlines()
['', ' This is the second line of the docstring.', ' ']
>>> trim(foo.__doc__)
'This is the second line of the docstring.'
修剪后,这些文档字符串是等效的
def foo():
"""A multi-line
docstring.
"""
def bar():
"""
A multi-line
docstring.
"""
版权
本文档已置于公共领域。
致谢
“规范”文本主要来自 Guido van Rossum 编写的 PEP 8。
本文档借鉴了 Python Doc-SIG 档案库中的想法。感谢所有过去和现在的成员。
来源:https://github.com/python/peps/blob/main/peps/pep-0257.rst
上次修改时间:2024-04-17 11:35:59 GMT