是否应该在类和__init__ docstrings中记录哪些内容?

cau*_*ima 24 python docstring code-documentation

我没有找到关于应该在类和__init__文档字符串中记录什么的最佳实践.有时我发现构造函数参数已经在docstring类中记录,有时会在__init__docstring 中描述.我更喜欢在类docstring中描述构造,因为这是您在创建新实例时调用的内容.但是应该在__init__docstring方法中记录什么呢?


编辑:

我知道google styleguidegoogle docstring样式示例,但两者都没有回答我的问题.文档字符串样式的例子确实说

__init__方法可以记录在类级别docstring中,也可以记录在__init__方法本身的docstring中.任何一种形式都是可以接受的,但这两种形式不应混合.选择一种约定来记录__init__方法并与之保持一致.

但是如果我选择将__init__函数的docstring 放入类级docstring中,那么__init__docstring 应该包含什么?

Eri*_*got 23

PEP 257(文档字符串 PEP)中有一个官方答案,可以说是权威的:

类构造函数应记录在其__init__方法的文档字符串中。

这是非常合乎逻辑的,因为这是函数和方法的常用过程,__init__()也不例外。

因此,这会将代码及其文档放在同一个地方,这有助于维护。

最后,向用户显示文档的工具(如 Jupyter 或内置 Python shell 命令help())更有可能正确显示代码的文档。实际上,当您在class上寻求帮助时,它们确实会__init__()自动显示文档字符串,因此这是遵循将初始化文档放在.__init__()

  • 幸运的是,这个注释并不正确:`help(MyClass)`显示了该类的所有方法,而`__init__()`就是其中之一,因此用户确实拥有创建对象所需的信息。这与官方的要求是一致的。此外,当您请求类构造函数的参数(使用 shift+tab)时,像 Jupyter Notebook 这样的工具会执行类似的操作:它会显示类_和 init docstring_。其寓意是,遵循一些共同的惯例是非常有帮助的——尤其是当它是一个好的惯例时。 (4认同)
  • 你说得对,那么 PEP 的建议就非常好。我仍然不喜欢在帮助输出中滚动到“__init__()”——同样,这是最终用户永远看不到的函数,但预计会知道它被无形地重新映射到类的名称。就文档可读性/显而易见性而言,这有点丑陋,但我想这只是为你编程。感谢您的更正,我将在我的类菜鸟文档字符串中写“see __init__()”(其中我将有很多使用我的模块)。 (2认同)
  • 有趣的补充:在实例化类时,Spyder 自动使用 `ClassName.__doc__` 的内容进行制表符自动完成,而不是 `ClassName.__init__.__doc__` 的内容。因此,这使得 *class* 中的文档对最终用户来说更加有用。另外,正如其他人所说,NumpyDoc 还说要在 Class docstring 中记录构造函数。最后,“help(MyClass)”似乎没有将“__init__”帮助放在顶部,这使得查找构造函数参数变得很烦人! (2认同)
  • 我认为 Spyder 和 NumpyDoc 都忽略了一个事实,即存在一个约定,它会产生您观察到的不良结果。就我个人而言,我不介意 `help(MyClass)` 将 `__init__()` 文档字符串放在底部,因为该命令实际上要求有关类的帮助,因此有关该类提供的信息应该放在第一位。无论提供帮助的计划选择何种惯例,获得良好且一致行为的唯一方法是每个人都遵循标准。 (2认同)

sal*_*ssi 9

我亲自尝试使用谷歌风格指南尽可能

当你用__init__它创建一个新实例时,应该记录哪些成员变量被初始化。然后其他人知道当他们稍后需要在他们的代码中访问它们时他们可以期待什么。

来自谷歌风格指南的示例:

class SampleClass(object):
    """Summary of class here.

    Longer class information....
    Longer class information....

    Attributes:
        likes_spam: A boolean indicating if we like SPAM or not.
        eggs: An integer count of the eggs we have laid.
    """

    def __init__(self, likes_spam=False):
        """Inits SampleClass with blah."""
        self.likes_spam = likes_spam
        self.eggs = 0

    def public_method(self):
        """Performs operation blah."""
Run Code Online (Sandbox Code Playgroud)

  • 我也尝试使用该 guid,但它没有回答我的问题,正如我在更新的问题中所述。 (4认同)

Dem*_*mis 7

该类的实际用法是通过诸如这样的命令初始化的SampleClass(args),并且永远不会输入任何用户SampleClass.__init__(args),因此从最终用户的角度来看,当他们感到困惑时,他们更有可能输入

help(SampleClass)
Run Code Online (Sandbox Code Playgroud)

代替

help(SampleClass.__init__)
Run Code Online (Sandbox Code Playgroud)

因此,我认为将所有文档放入SampleClassdocstring 是有意义的。
并在__init__的文档字符串中添加“请参阅help(SampleClass)以获取更多信息”,以防万一有人(或某些程序)查看它。


Bri*_*rig 7

__init__Numpy 说你应该在类文档中记录。https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard

这是一个示例,您可以看到哪里__init__没有文档字符串。相反,它显示在类文档中。 https://github.com/numpy/numpy/blob/master/numpy/core/records.py

  • 这违反了 PEP 257 的官方指南。 (2认同)

dsh*_*han 6

类文档应该包括对象的公共组件。该__init__参数可能会或可能不会是公开的,所以它们是否包含在类文档字符串或不依赖于对象的设计。

PEP 257 中的完整段落指出:

类的文档字符串应总结其行为并列出公共方法和实例变量。如果该类打算被子类化,并且具有用于子类的附加接口,则应单独列出该接口(在文档字符串中)。类构造函数应记录在其__init__ 方法的文档字符串中。单个方法应该由它们自己的文档字符串记录。

谷歌的风格指南规定:

类应该在描述类的类定义下方有一个文档字符串。如果您的类具有公共属性,则应将它们记录在此处的 Attributes 部分中,并遵循与函数的 Args 部分相同的格式。

因此,对参数是否文档确定铰链__init__公众。如果对象的目的是让用户构建自己的实例,则__init__参数应记录在类文档字符串中。然而,如果一个对象在内部构造然后返回给用户,类文档应该只引用对象的公共方面。

因此,来自 google 的以下示例表明likes_spam参数 from__init__是公开的:

class SampleClass(object):
    """Summary of class here.

    Longer class information....
    Longer class information....

    Attributes:
        likes_spam: A boolean indicating if we like SPAM or not.
        eggs: An integer count of the eggs we have laid.
    """

    def __init__(self, likes_spam=False):
        """Inits SampleClass with blah."""
        self.likes_spam = likes_spam
        self.eggs = 0

    def public_method(self):
        """Performs operation blah."""
Run Code Online (Sandbox Code Playgroud)

但是,下面的公共likes_spam属性是__init__基于两个内部参数spam_count和期间确定的like_threshold。因此,likes_spam记录在类文档字符串中,而spam_countlike_threshold记录在__init__文档字符串中。

class SampleClass(object):
    """Summary of class here.

    Longer class information....
    Longer class information....

    Attributes:
        likes_spam: A boolean indicating if we like SPAM or not.
        eggs: An integer count of the eggs we have laid.
    """

    def __init__(self, spam_count, like_threshold=1):
        """Inits SampleClass.

        Args:
            spam_count: The amount of SPAM consumed.
            like_threshold: The threshold consumed that indicates 
                whether we like SPAM.
        """
        self.likes_spam = spam_count > like_threshold
        self.eggs = 0

    def public_method(self):
        """Performs operation blah."""
Run Code Online (Sandbox Code Playgroud)