Python最常见的文档字符串格式是什么?

1135

我见过几种不同风格的Python文档字符串编写方式,哪些是最受欢迎的风格?


6
在http://www.python.org/dev/peps/pep-0008/中有一个专门介绍文档字符串的部分。 - mechanical_meat
39
我认为这个问题不够清晰,因为PEP-257和PEP-8只是为docstrings建立基础,但是epydocdoxygensphinx呢?有没有人有统计数据,它们中的一个会取代其他选项吗?在这种情况下,太多的选择可能会造成困扰。 - sorin
1
@sorin,我也想知道最常用的标记是什么,如果有的话。但我认为答案是没有一种标记真正非常常见:人们倾向于直接查看Python源代码,而不是转换为HTML。因此,最有用的方法是保持一致,以便人类可读性最优化,并且没有明确的标记。 - poolie
3
PyCharm 的自动补全方式非常有趣,我认为这是运行它所需的指令的一个不错的实现: def foo(self, other):\n\t"""\n\t(空白行)\n\t:param other: \n\t:return:\n\t""" - Matteo Ferla
2
这些答案中哪个是默认与VS Code文档解析器配合使用的? - William Entriken
@WilliamEntriken 至少在 VS Code 中可以使用 Google 风格,其他的没有检查过。 - xuiqzy
6个回答

1389

格式

Python文档字符串可以按照其他帖子所示的几种格式编写。然而,默认的Sphinx文档字符串格式未被提及,它基于reStructuredText(reST)。您可以在这篇博客文章中获取有关主要格式的一些信息。

请注意,PEP 287建议使用reST。

以下是文档字符串中主要使用的格式。

- Epytext

历史上,像javadoc一样的风格很普遍,因此将其作为Epydoc(使用称为Epytext格式)生成文档的基础。

例如:

"""
This is a javadoc style.

@param param1: this is a first param
@param param2: this is a second param
@return: this is a description of what is returned
@raise keyError: raises an exception
"""

- reST

现在,更为普遍的格式是由Sphinx用于生成文档的reStructuredText(reST)格式。 注意:在JetBrains PyCharm中默认使用它(在定义方法后键入三个引号并按Enter)。它还是Pyment中的默认输出格式。

示例:

"""
This is a reST style.

:param param1: this is a first param
:param param2: this is a second param
:returns: this is a description of what is returned
:raises keyError: raises an exception
"""

- 谷歌

谷歌有自己的格式,通常被广泛使用。它也可以通过Sphinx解释(即使用Napoleon插件)。

示例:

"""
This is an example of Google style.

Args:
    param1: This is the first param.
    param2: This is a second param.

Returns:
    This is a description of what is returned.

Raises:
    KeyError: Raises an exception.
"""

甚至更多例子

- Numpydoc

请注意,Numpy建议遵循他们自己的numpydoc,基于Google格式并可由Sphinx使用。

"""
My numpydoc description of a kind
of very exhautive numpydoc format docstring.

Parameters
----------
first : array_like
    the 1st param name `first`
second :
    the 2nd param
third : {'value', 'other'}, optional
    the 3rd param, by default 'value'

Returns
-------
string
    a value in a string

Raises
------
KeyError
    when a key error
OtherError
    when an other error
"""

转换/生成

可以使用类似Pyment的工具自动生成Python项目的文档字符串,以便对尚未有文档说明的项目进行记录,或将现有的文档字符串(可以混合多种格式)从一种格式转换为另一种格式。

注意:这些示例来自Pyment文档


25
我想补充一点,reST 是 JetBrains PyCharm 默认使用的文档格式。只需在定义方法后键入三个引号并按回车即可。https://www.jetbrains.com/pycharm/help/creating-documentation-comments.html - Felipe
28
最全面的回答,包括历史感和目前最佳实践。现在我们需要一些社区动态来形成新的“最佳”格式,并且需要额外的社区努力来创建从所有其他格式迁移到新格式的迁移工具,以便我们实际上能够发展出最佳实践。 Translated: 这篇文章要求提供一个具有历史意义和当前最佳实践的全面回答。现在我们需要一些社群运动朝着新的"最佳"格式方向,并需要更多的社区努力来创造迁移工具,以将所有其他格式迁移到新的格式中,这样我们才能真正演变出最佳实践。 - BobHy
3
嗨@daouzli,谷歌风格的链接是404错误。我相信这个链接是正确的。你还可以添加Sphinx谷歌样式示例。非常好的回答。编辑备注:我已经自己编辑了您的答案。 - voy
5
不错的回答。我敢说你可以在PyCharm(JetBrains)中更改默认的文档字符串格式:设置 --> 工具 --> Python集成工具 --> 文档字符串格式。祝好运! - Jackssn
5
我很惊讶没有人评论第一行文本:严格来说目前是正确的,但我感觉更好的方式是把它放在三引号后的第一行。 PEP 8和PEP 257几乎在所有示例中都这样做。 PEP 287按照你的方式做,但根据我的经验,这种情况并不常见。 - Lapinot
显示剩余5条评论

354

Google风格指南包含了一份出色的Python风格指南。其中包括易于阅读的注释和文档字符串语法规范,比PEP-257提供更好的指导。例如:

def square_root(n):
    """Calculate the square root of a number.

    Args:
        n: the number to get the square root of.
    Returns:
        the square root of n.
    Raises:
        TypeError: if n is not a number.
        ValueError: if n is negative.

    """
    pass

我希望将其扩展,以在参数中包括类型信息,就像在这个Sphinx文档教程中描述的那样。例如:

def add_value(self, value):
    """Add a new value.

       Args:
           value (str): the value to add.
    """
    pass

49
我觉得“在文档字符串中使用签名”的方式非常冗长而啰嗦。对于 Python 3+,函数注释是一种更加简洁的方法。如果使用伪强类型,那么情况会更糟糕:Python 的鸭子类型更好。 - Evpok
29
是的,但至少它给出了期望的鸭子类型的提示,而大多数开发人员还没有使用Python 3。 - Anentropic
4
就我个人而言,我不喜欢函数注解。如果要在注解中使用类,可能需要进行不必要的导入;如果要在注解中使用字符串,你可能很快就会用尽水平空间来描述它们。到目前为止,我还没有看到使用它们的意义所在。 - OdraEncoded
7
谷歌的风格指南建议使用描述性而非陈述性的注释,例如,“从 Bigtable 获取行”而不是“获取 Bigtable 行”。因此,将“Calculate…”更改为“Calculates…”会使您的示例与其余注释更加一致,即“Returns”和“Raises”。 - jds
3
注意:遵循谷歌的风格,使用描述性语言而非命令式语言,例如“计算…”和“添加…” - sbeliakov
显示剩余2条评论

244

文档字符串规范在PEP-257中有比PEP-8更详细的内容。

然而,文档字符串似乎比代码的其他部分更加个人化。不同的项目将有自己的标准。

我倾向于始终包含文档字符串,因为它们往往能够非常快速地展示如何使用函数以及它的功能。

我喜欢保持一致性,无论字符串的长度如何。当缩进和间距一致时,我喜欢代码的外观。这意味着我使用:

def sq(n):
    """
    Return the square of n. 
    """
    return n * n

结束:

def sq(n):
    """Returns the square of n."""
    return n * n

在较长的文档字符串中,往往会忽略第一行的注释:

def sq(n):
    """
    Return the square of n, accepting all numeric types:

    >>> sq(10)
    100

    >>> sq(10.434)
    108.86835599999999

    Raises a TypeError when input is invalid:

    >>> sq(4*'435')
    Traceback (most recent call last):
      ...
    TypeError: can't multiply sequence by non-int of type 'str'

    """
    return n*n

我觉得以这种方式开头的文档字符串很凌乱。

def sq(n):
    """Return the squared result. 
    ...

100
请注意,PEP-8明确规定文档字符串应该被写成命令/指令,而不是描述,例如"""返回平方结果"""而不是"""返回平方结果"""。尽管如此,我个人会像Tim在这里一样编写我的文档字符串,而不是遵循PEP的建议。 - Cam Jackson
69
我不同意那个建议(使用祈使句),因为超过一句话就会变得很别扭。此外,你是在描述一个函数,而不是告诉读者该做什么。 - mk12
14
注意:对于规定性而不是描述性文档字符串的规范实际上出现在PEP-257,而不是PEP-8。我来自Java的传统,我曾经描述函数,但当我的编程范式从面向对象转换为过程化时,我最终开始使用祈使语气。当我开始使用pycco生成文学编程风格的文档时,这就非常明显为什么建议使用祈使语气了。你应该根据你的范式进行选择。 - karan.dodia
28
祈使语气是一种语法语气。(抱歉) - Dawn Drescher
7
Git提交信息应该以命令的形式而不是描述的形式编写,它们还在“描述”代码的更改,“而不是告诉读者该做什么”。因此,我认为将描述写成命令只是一种惯例。 - onepiece
显示剩余3条评论

67

显然没人提到过:你也可以使用Numpy Docstring Standard,它在科学界得到了广泛应用。

Napoleon sphinx扩展程序(在@Nathan的回答中推荐)支持Numpy样式的文档字符串,并对两者进行了简短的比较

最后给出一个基本示例,以便了解其外观:

def func(arg1, arg2):
    """Summary line.

    Extended description of function.

    Parameters
    ----------
    arg1 : int
        Description of arg1
    arg2 : str
        Description of arg2

    Returns
    -------
    bool
        Description of return value

    See Also
    --------
    otherfunc : some related other function

    Examples
    --------
    These are written in doctest format, and should illustrate how to
    use the function.

    >>> a=[1,2,3]
    >>> print [x + 3 for x in a]
    [4, 5, 6]
    """
    return True

3
在我看来,NumPy格式在宽屏显示器上占用了太多垂直空间(除非您使用90度旋转的屏幕,但我想大多数人不会这样做)。因此,在可读性和功能方面,我认为Google格式是一个很好的选择。 - Semanino
6
我认为这有一定的主观性。一旦你有了更复杂的文档字符串(包含不同部分、示例等,无论格式如何都需要很多垂直空间),我发现numpydoc格式更易于阅读/结构更好。 - joris
2
个人认为,如果docstring太长以至于影响模块的可读性,那么最好将其放在文档中而不是源代码中。 - Jonathan Hartley

12

24
我经常使用 ipython 来测试一个库,并且它使得读取文档字符串变得非常简单 —— 我所需要做的就是输入 your_module.some_method_im_curious_about?,然后我就可以得到一个非常漂亮的输出,其中包括文档字符串。 - Thanatos
9
使用API或编写插件的用户都很可能会查看代码并需要理解它。我认为在Python中,注释比Java或C#更加关键,因为类型没有声明。如果注释能够大致说明传递和返回的数据类型,那将有很大帮助。(否则,你必须手动遍历所有代码,并计算给定参数必须...在这里是可迭代的...在那里支持索引...在最后支持数字减法...啊!它基本上是一个整数数组。注释会有所帮助!) - Jon Coombs
2
嗯,不太对。文档字符串并不是不可见的,这也是其中的一点。如果您在记录的函数/方法/类上运行help函数,则可以查看文档字符串(即使只能访问已编译的模块)。个人认为,在选择文档字符串约定时应记住这一点(即它旨在按原样阅读)。 - skyking
注意:链接视频已被删除。 - wovano

8
我建议使用Vladimir Keleshev的Python程序pep257来检查你的文档字符串是否符合PEP-257Numpy Docstring Standard的要求,以描述参数、返回值等。
像pylint和pep8一样,pep257会报告你与标准不符的地方。

1
在“我应该如何正确记录参数、返回值、引发的异常等”这个语境中提到PEP-257是一个笑话——它对它们没有一句话(尽管代码示例显示了一些)。 在宽屏监视器上垂直空间很少(除非您使用一个旋转了90度的屏幕,但我猜大多数人不会),因此NumPy格式在我的看法中占用了太多的垂直空间。 因此,我认为Google格式是一个关于可读性和功能的好选择。 - Semanino
1
@Semanino,我在提到PEP257程序的上下文中提到了Numpy Docstring标准,而不是PEP-257。该程序现在被称为pydocstyle。pydocstyle允许您执行一些numpydoc检查,例如,pydocstyle --select=D4 tmp.py检查一系列文档字符串内容问题,包括部分命名。 - Finn Årup Nielsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接