Python编码规范PEP 8文章中提到了PEP 257,Docstring书写规范。什么是Docstring?简单的说Docstring是一种文档字符串,用于解释构造的作用。我们在函数、类或方法中将它放在首位来描述其作用。我们用三个单引号或双引号来声明docstring。
以下为官方PEP 257 — Docstring Conventions翻译的内容。
目录
摘要
本篇PEP文档主要对Python函数Docstring的语义和规范进行了相关阐述。
基本原理
PEP的目标是让程序员写出的Python Docstring高度结构化、规范化:文档字符串应该包含什么,如何书写(在文档字符里避免使用标记语法的情况下)。 PEP中包含的是约定俗成的东西,不是定律或严苛的语法。
一个通用的公约给编程提供了可维护性,清晰性,一致性,同时也提供了良好的编程习惯的基础。但它从来不会强迫你去按照它的标准做你不喜欢的事情。这就是Python!”
—Tim Peters on comp.lang.python, 2001-06-16
如果你不按约定编写代码,最多导致不够美观。但有些软件代码的编写必须按照约定来(比如 Docutils docstring 的处理系统)。总而言之,遵守约定,能给你带来最好的结果。
详细说明
什么是Docstring?
Docstring是模块、类、方法中的第一个声明性描述说明。比如docstring变成 __doc__ 类的special attribute of that object.
所有的modules一般都有Docstring,模块中的类和方法也应该有Docstring。公共方法 (包含 __init__ 构造器的方法) 也应该有Docstring。一个包的描述信息一般在包目录中文件__init__.py的Docstring中。
字符串类说明信息在Python代码中随处可见,通常用称为文档说明的一部分。这些信息不会被Python字节码编译器识别到,也不能被运行时对象属性访问。但是,有两类附加的docstring能被软件工具提取出来。
- 在一个模块、类或者__init__ 方法中一开始就出现的字符串描述信息,我们称之为 “attribute docstrings”
- 紧跟在一个 docstring 后面的字符串描述信息,被称为 “additional docstrings”
请参考 PEP 258 , “Docutils Design Specification”,里面有关于”attribute docstrings”和”additional docstrings”的详细说明。
下面是三种情况下,Docstring的一般写法:
- 正常情况下: “””三个双引号””” (单纯用三个双引号引起来)
- 如果有反斜线: r”””raw triple double quotes””” (在开头加字幕r)
- 如果使用统一字符编码标准:u”””Unicode triple-quoted strings””” . (在开头加字幕u)
一共有两种Docstring,单行的和多行的:
单行Docstring
单行Docstring用于显而易见的情况,将说明描述字符串写入一行即可。例如:
def kos_root(): """Return the pathname of the KOS root directory.""" global _kos_root if _kos_root: return _kos_root ...
注意:
- 即使是单行也要使用三引号,为的以后可以轻松扩展它。
- 关闭的引号应该和开始的引号在同一行,对于单行,这样看起来更好。
- Docstring的开始和结束不空行。
- 描述函数或方法的作用时应该使用命令式短语(“Do this”, “Return that”)而不是作为一段描述。比如,不要写“Returns the pathname …”。
- 单行Docstring不应该重申函数或方法的参数(因为可以通过内省得到)。 不要像这样:
def function(a, b): """function(a, b) -> list"""
上面的这种类型的文档说明只适用于C函数(例如内建函数)这样的无法内省的函数。然而,return值的类型无法由内省决定,因此这需要被注意。对于这种Docstring的首选形式是:
def function(a, b): """Do X and return a list."""
多行Docstring
多行Docstring的开始是一段摘要,就像单行Docstring一样,接下来是一个空行,然后是更多详细描述。摘要可以被自动索引工具所使用;关键在于,摘要适用于一行,并且使用一个空行与剩下的Docstring进行区分。摘要可以与开始引号在同一行或另起一行。整个文档字字符串的缩进应该与第一行的引号相同(参照下面的示例)。
在类的所有Docstring(一行或多行)之后插入一个空白行——通常来说,类的方法是通过一个空白行彼此分开的,所以Docstring需要一个空行来和类的第一个方法分开。
脚本(独立程序)的Docstring应该可以用作其“使用方法”消息,当脚本被调用时使用不正确或缺少的参数(或者可能使用“-h”选项,用于“帮助”)进行打印。这样一个Docstring应该记录脚本的功能和命令行语法,环境变量和文件。使用方法信息可以是相当详细的(随便占个几屏),并且应该足以指导新用户正确使用命令,以及高级用户也可以完整快速的索引到全部选项和参数。
模块的Docstring通常应列出由模块导出的类,异常和函数(以及任何其他对象),其中包含每个模块的一行摘要。(这些摘要通常比对象的Docstring中的摘要行提供的细节更少)。软件包的Docstring(即软件包的__init__.py模块的Docstring)也应该列出软件包导出的模块和子包。
函数或方法的Docstring应该总结其行为并记录其参数,返回值,副作用,引发的异常以及可以调用的限制(如果适用的话)。 应该指出可选参数。 应该记录关键字参数是否是接口的一部分。
类的Docstring应该总结其行为并列出公共方法和实例变量。如果该类旨在被子类化,并且有一个子类的附加接口,则该接口应该单独列出(在Docstring中)。类构造函数应该在Docstring中记录其__init__方法。私有方法应该由他们自己的Docstring记录。
如果一个类对另一个类进行子类化,并且其行为大部分从该类继承,则其Docstring应该提及这一点,并总结出差异。 使用动词“override”表示子类方法替换超类方法,不调用超类方法; 使用动词“extend”来表示一个子类方法调用超类方法(除了自己的行为)。
在运行文本时,请勿使用Emacs习俗来对函数或方法的参数进行首字母大写。Python区分大小写,参数名称可以用于关键字参数,因此Docstring应该记录正确的参数名称。最好在单独的行上列出每个参数。 例如:
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 ...
除非整个Docstring串符合一行,否则将结束引号单独起一行。 这样可以支持使用Emacs的fill-paragraph命令。
处理Docstring缩进
Docstring处理工具将从Docstring的第二行和另外一行剥离均匀的缩进量,等于第一行之后的所有非空白行的最小缩进。文档字符串的第一行中的任何缩进(即,直到第一个换行符)都是微不足道的,并被删除。Docstring中后续行的相对缩进被保留。 应从文本字符串的开头和结尾删除空白行。
由于代码比文字表述更准确,这里是算法的实现:
ef 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.maxint 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.maxint: 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)
此示例中的Docstring包含两个换行符,因此为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.'
经过裁剪处理后,下面两段代码的Docstring是等价的:
def foo(): """A multi-line docstring. """ def bar(): """ A multi-line docstring. """