如何记录带有参数的方法?

发布于 2025-01-03 20:26:06 字数 841 浏览 1 评论 0原文

如何使用 Python 的文档字符串来记录带有参数的方法?

PEP 257 给出了这个例子:

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
    ...

这是大多数 Python 开发人员使用的约定吗?

Keyword arguments:
<parameter name> -- Definition (default value if any)

我期待一些更正式的东西,例如

def complex(real=0.0, imag=0.0):
    """Form a complex number.

    @param: real The real part (default 0.0)
    @param: imag The imaginary part (default 0.0)

    """
    if imag == 0.0 and real == 0.0: return complex_zero
    ...

环境:Python 2.7.1

How to document methods with parameters using Python's documentation strings?

PEP 257 gives this example:

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
    ...

Is this the convention used by most Python developers?

Keyword arguments:
<parameter name> -- Definition (default value if any)

I was expecting something a little bit more formal such as

def complex(real=0.0, imag=0.0):
    """Form a complex number.

    @param: real The real part (default 0.0)
    @param: imag The imaginary part (default 0.0)

    """
    if imag == 0.0 and real == 0.0: return complex_zero
    ...

Environment: Python 2.7.1

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

德意的啸 2025-01-10 20:26:06

由于文档字符串是自由格式的,因此它实际上取决于您用来解析代码以生成 API 文档的内容。

我建议熟悉 Sphinx 标记,因为它被广泛使用,并正在成为记录 Python 项目的事实上的标准,部分原因是优秀的 readthedocs.org 服务。 转述示例作为 Python 片段的 Sphinx 文档:

def send_message(sender, recipient, message_body, priority=1) -> int:
   """
   Send a message to a recipient.

   :param str sender: The person sending the message
   :param str recipient: The recipient of the message
   :param str message_body: The body of the message
   :param priority: The priority of the message, can be a number 1-5
   :type priority: integer or None
   :return: the message id
   :rtype: int
   :raises ValueError: if the message_body exceeds 160 characters
   :raises TypeError: if the message_body is not a basestring
   """

此标记支持 文档之间的交叉引用等。请注意,Sphinx 文档使用(例如):py:attr:,而您在从源代码记录时可以只使用 :attr:

当然,还有其他工具来记录 API。有更经典的 Doxygen 它使用 \param 命令,但这些命令并不是像 Sphinx 那样专门设计用于记录 Python 代码。

请注意,有一个 类似问题,其中 类似的答案在这里......

Since docstrings are free-form, it really depends on what you use to parse code to generate API documentation.

I would recommend getting familiar with the Sphinx markup, since it is widely used and is becoming the de-facto standard for documenting Python projects, in part because of the excellent readthedocs.org service. To paraphrase an example from the Sphinx documentation as a Python snippet:

def send_message(sender, recipient, message_body, priority=1) -> int:
   """
   Send a message to a recipient.

   :param str sender: The person sending the message
   :param str recipient: The recipient of the message
   :param str message_body: The body of the message
   :param priority: The priority of the message, can be a number 1-5
   :type priority: integer or None
   :return: the message id
   :rtype: int
   :raises ValueError: if the message_body exceeds 160 characters
   :raises TypeError: if the message_body is not a basestring
   """

This markup supports cross-referencing between documents and more. Note that the Sphinx documentation uses (e.g.) :py:attr: whereas you can just use :attr: when documenting from the source code.

Naturally, there are other tools to document APIs. There's the more classic Doxygen which uses \param commands but those are not specifically designed to document Python code like Sphinx is.

Note that there is a similar question with a similar answer in here...

我很OK 2025-01-10 20:26:06

根据我的经验,numpy 文档字符串约定(PEP257超集)是最广泛遵循的约定,也受到工具的支持,例如 狮身人面像

一个例子:

Parameters
----------
x : type
    Description of parameter `x`.

Based on my experience, the numpy docstring conventions (PEP257 superset) are the most widely-spread followed conventions that are also supported by tools, such as Sphinx.

One example:

Parameters
----------
x : type
    Description of parameter `x`.
热风软妹 2025-01-10 20:26:06

约定:

工具:


更新:从 Python 3.5 开始,您可以使用 类型提示,这是一种紧凑的、机器可读的语法:

from typing import Dict, Union

def foo(i: int, d: Dict[str, Union[str, int]]) -> int:
    """
    Explanation: this function takes two arguments: `i` and `d`.
    `i` is annotated simply as `int`. `d` is a dictionary with `str` keys
    and values that can be either `str` or `int`.

    The return type is `int`.

    """

这种语法的主要优点是它是由语言定义的并且是明确的,因此像 PyCharm 这样的工具可以轻松地利用 它。

Conventions:

Tools:


Update: Since Python 3.5 you can use type hints which is a compact, machine-readable syntax:

from typing import Dict, Union

def foo(i: int, d: Dict[str, Union[str, int]]) -> int:
    """
    Explanation: this function takes two arguments: `i` and `d`.
    `i` is annotated simply as `int`. `d` is a dictionary with `str` keys
    and values that can be either `str` or `int`.

    The return type is `int`.

    """

The main advantage of this syntax is that it is defined by the language and that it's unambiguous, so tools like PyCharm can easily take advantage from it.

说好的呢 2025-01-10 20:26:06

python 文档字符串是自由格式,您可以按照您喜欢的任何方式记录它。

示例:

def mymethod(self, foo, bars):
    """
    Does neat stuff!
    Parameters:
      foo - a foo of type FooType to bar with.
      bars - The list of bars
    """

现在,有一些约定,但 python 不强制执行其中任何约定。有些项目有自己的惯例。一些使用文档字符串的工具也遵循特定的约定。

python doc strings are free-form, you can document it in any way you like.

Examples:

def mymethod(self, foo, bars):
    """
    Does neat stuff!
    Parameters:
      foo - a foo of type FooType to bar with.
      bars - The list of bars
    """

Now, there are some conventions, but python doesn't enforce any of them. Some projects have their own conventions. Some tools to work with docstrings also follow specific conventions.

メ斷腸人バ 2025-01-10 20:26:06

如果您计划使用 Sphinx 来记录您的代码,它能够通过其“签名”功能为您的参数生成格式良好的 HTML 文档。 http://sphinx-doc.org/domains.html#signatures

If you plan to use Sphinx to document your code, it is capable of producing nicely formatted HTML docs for your parameters with their 'signatures' feature. http://sphinx-doc.org/domains.html#signatures

一梦等七年七年为一梦 2025-01-10 20:26:06

正如这里的其他答案已经指出的那样,主流可能是 Sphinx 方式,以便您稍后可以使用 Sphinx 生成那些精美的文档。

话虽如此,我个人偶尔也会使用内联评论风格。

def complex(  # Form a complex number
        real=0.0,  # the real part (default 0.0)
        imag=0.0  # the imaginary part (default 0.0)
        ):  # Returns a complex number.
    """Form a complex number.

    I may still use the mainstream docstring notation,
    if I foresee a need to use some other tools
    to generate an HTML online doc later
    """
    if imag == 0.0 and real == 0.0:
        return complex_zero
    other_code()

这里还有一个例子,内联记录了一些微小的细节:

def foo(  # Note that how I use the parenthesis rather than backslash "\"
          # to natually break the function definition into multiple lines.
        a_very_long_parameter_name,
            # The "inline" text does not really have to be at same line,
            # when your parameter name is very long.
            # Besides, you can use this way to have multiple lines doc too.
            # The one extra level indentation here natually matches the
            # original Python indentation style.
            #
            # This parameter represents blah blah
            # blah blah
            # blah blah
        param_b,  # Some description about parameter B.
            # Some more description about parameter B.
            # As you probably noticed, the vertical alignment of pound sign
            # is less a concern IMHO, as long as your docs are intuitively
            # readable.
        last_param,  # As a side note, you can use an optional comma for
                     # your last parameter, as you can do in multi-line list
                     # or dict declaration.
        ):  # So this ending parenthesis occupying its own line provides a
            # perfect chance to use inline doc to document the return value,
            # despite of its unhappy face appearance. :)
    pass

好处(正如 @mark-horvath 已经在另一条评论中指出的那样)是:

  • 最重要的是,参数和它们的文档总是在一起,这带来了以下好处:
  • 更少的打字(没有需要重复变量名称)
  • 更改/删除变量时更容易维护。重命名某个参数后,永远不会出现一些孤立参数文档段落。
  • 并且更容易找到缺失的评论。

现在,有些人可能会认为这种风格看起来“丑陋”。但我想说“丑”是一个主观词。更中性的说法是,这种风格不是主流,所以你可能会觉得不太熟悉,从而不太舒服。再次强调,“舒适”也是一个主观词。但重点是,上述所有好处都是客观的。如果你遵循标准方式,你就无法实现它们。

希望将来的某一天,会有一个文档生成器工具也可以使用这种内联样式。这将推动采用。

PS:这个答案源于我自己在认为合适的时候使用内联注释的偏好。我也使用相同的内联样式来记录字典

The mainstream is, as other answers here already pointed out, probably going with the Sphinx way so that you can use Sphinx to generate those fancy documents later.

That being said, I personally go with inline comment style occasionally.

def complex(  # Form a complex number
        real=0.0,  # the real part (default 0.0)
        imag=0.0  # the imaginary part (default 0.0)
        ):  # Returns a complex number.
    """Form a complex number.

    I may still use the mainstream docstring notation,
    if I foresee a need to use some other tools
    to generate an HTML online doc later
    """
    if imag == 0.0 and real == 0.0:
        return complex_zero
    other_code()

One more example here, with some tiny details documented inline:

def foo(  # Note that how I use the parenthesis rather than backslash "\"
          # to natually break the function definition into multiple lines.
        a_very_long_parameter_name,
            # The "inline" text does not really have to be at same line,
            # when your parameter name is very long.
            # Besides, you can use this way to have multiple lines doc too.
            # The one extra level indentation here natually matches the
            # original Python indentation style.
            #
            # This parameter represents blah blah
            # blah blah
            # blah blah
        param_b,  # Some description about parameter B.
            # Some more description about parameter B.
            # As you probably noticed, the vertical alignment of pound sign
            # is less a concern IMHO, as long as your docs are intuitively
            # readable.
        last_param,  # As a side note, you can use an optional comma for
                     # your last parameter, as you can do in multi-line list
                     # or dict declaration.
        ):  # So this ending parenthesis occupying its own line provides a
            # perfect chance to use inline doc to document the return value,
            # despite of its unhappy face appearance. :)
    pass

The benefits (as @mark-horvath already pointed out in another comment) are:

  • Most importantly, parameters and their doc always stay together, which brings the following benefits:
  • Less typing (no need to repeat variable name)
  • Easier maintenance upon changing/removing variable. There will never be some orphan parameter doc paragraph after you rename some parameter.
  • and easier to find missing comment.

Now, some may think this style looks "ugly". But I would say "ugly" is a subjective word. A more neutual way is to say, this style is not mainstream so it may look less familiar to you, thus less comfortable. Again, "comfortable" is also a subjective word. But the point is, all the benefits described above are objective. You can not achieve them if you follow the standard way.

Hopefully some day in the future, there will be a doc generator tool which can also consume such inline style. That will drive the adoption.

PS: This answer is derived from my own preference of using inline comments whenever I see fit. I use the same inline style to document a dictionary too.

梦里°也失望 2025-01-10 20:26:06

Sphinx Python 3 键入最小可运行示例

只是为了使其他答案所说的更具体:

build.sh

sphinx-build . out

conf.py

import os
import sys
sys.path.insert(0, os.path.abspath('.'))
extensions = [ 'sphinx.ext.autodoc' ]
autodoc_default_options = {
    'members': True,
    'show-inheritance': True,
}
autodoc_typehints = "description"

index.rst

.. automodule:: main

main.pyrequirements.txt

class MyClass:
    """
    This class does that.
    """
    def __init__(self, i):
        self.i = i

def do_this(parameter1: int, parameter2: MyClass) -> int:
   """
   This function does this.

   :param parameter1: my favorite int
   :param parameter2: my favorite class
   :return: what it returns
   """
   return parameter1 + parameter2.i

Sphinx==6.1.3

out/index.html< 上的输出/code>:

在此处输入图像描述

如果我们删除:

autodoc_typehints = "description"

键入类型将显示在函数签名上:

在此处输入图像描述

预输入等效内容

以下产生相同的效果输出为版本autodoc_typehints = "description",但参数名称重复较多:

def do_this(parameter1, parameter2):
   """
   This function does this.

   :param parameter1: my favorite int
   :type parameter1: int
   :param parameter2: my favorite class
   :type parameter2: MyClass
   :return: what it returns
   :rtype: int
   """
   return parameter1 + parameter2.i

梦想:参数文档字符串

我们必须为每个 重新输入参数名称,这很糟糕:参数参数名称:。目前看来还没有好的解决办法。将来可能会通过一些方式解决这个问题:

  • Sphinx 可以向参数添加 #: 文档注释。此 Sphinx 扩展已适用于实例属性,如下所述:如何显示实例sphinx 文档中的属性?

    类MyClass:
        def __init__(self, par1: int):
            #:我最喜欢的属性!
            self.var1:int = par1 
    

    那么为什么不给我们:

    def do_this(
        #:我最喜欢的整数
        参数1:整数,
        #:我最喜欢的课
        参数2:我的类
    )->整数:
    
  • Python 最终可以真正原生支持参数文档字符串!

    def do_this(
        参数1:整数,
        ”“”
        我最喜欢的整数
        ”“”
    
        参数2:我的类
        ”“”
        我最喜欢的课
        ”“”
    )->整数:
    

TODO 查找这些功能请求!

同样的愿望也提到: https://stackoverflow.com/a/39581355/895245

其他有用的打字相关需要知道的事情

在 Python 3.10、Ubuntu 22.10 上测试。

Sphinx Python 3 typing minimal runnable example

Just to make what other answers said more concrete:

build.sh

sphinx-build . out

conf.py

import os
import sys
sys.path.insert(0, os.path.abspath('.'))
extensions = [ 'sphinx.ext.autodoc' ]
autodoc_default_options = {
    'members': True,
    'show-inheritance': True,
}
autodoc_typehints = "description"

index.rst

.. automodule:: main

main.py

class MyClass:
    """
    This class does that.
    """
    def __init__(self, i):
        self.i = i

def do_this(parameter1: int, parameter2: MyClass) -> int:
   """
   This function does this.

   :param parameter1: my favorite int
   :param parameter2: my favorite class
   :return: what it returns
   """
   return parameter1 + parameter2.i

requirements.txt

Sphinx==6.1.3

Output on out/index.html:

enter image description here

If we remove:

autodoc_typehints = "description"

typing types show on the function signature instead:

enter image description here

Pre-typing equivalent

The following produces the same output as the version with autodoc_typehints = "description", but with a bit more parameter name repetition:

def do_this(parameter1, parameter2):
   """
   This function does this.

   :param parameter1: my favorite int
   :type parameter1: int
   :param parameter2: my favorite class
   :type parameter2: MyClass
   :return: what it returns
   :rtype: int
   """
   return parameter1 + parameter2.i

The dream: argument docstrings

It is bad that we have to retype argument names for every :param argumentname:. There doesn't seem to be a good solution to this currently. Some ways it might be solved in the future:

  • Sphinx could add #: doc comments to parameters. This Sphinx extension already works for instance attributes as mentioned at: How to show instance attributes in sphinx doc?

    class MyClass:
        def __init__(self, par1: int):
            #: My favorite attribute!
            self.var1: int = par1 
    

    so why not give us:

    def do_this(
        #: my favorite int
        parameter1: int,
        #: my favorite class
        parameter2: MyClass
    ) -> int:
    
  • Python could finally actually support argument docstrings natively!

    def do_this(
        parameter1: int,
        """
        my favorite int
        """
    
        parameter2: MyClass
        """
        my favorite class
        """
    ) -> int:
    

TODO find feature requests for these!

Same desire also mentioned at: https://stackoverflow.com/a/39581355/895245

Other useful typing related things to know

Tested on Python 3.10, Ubuntu 22.10.

香橙ぽ 2025-01-10 20:26:06

基于类型提示答案(https://stackoverflow.com/a/9195565/2418922),它提供了更好的结构化方式来记录参数类型,还存在一种结构化方式来记录参数的类型和描述:

def copy_net(
    infile: (str, 'The name of the file to send'),
    host: (str, 'The host to send the file to'),
    port: (int, 'The port to connect to')):

    pass

示例来自:https://pypi.org/project/autocommand/

Building upon the type-hints answer (https://stackoverflow.com/a/9195565/2418922), which provides a better structured way to document types of parameters, there exist also a structured manner to document both type and descriptions of parameters:

def copy_net(
    infile: (str, 'The name of the file to send'),
    host: (str, 'The host to send the file to'),
    port: (int, 'The port to connect to')):

    pass

example adopted from: https://pypi.org/project/autocommand/

谜兔 2025-01-10 20:26:06

文档字符串仅在交互式环境中有用,例如 Python shell。当记录不会交互使用的对象(例如内部对象、框架回调)时,您不妨使用常规注释。这是我用来将缩进注释挂在项目上的样式,每个注释都在自己的行上,这样您就知道该注释适用于:

def Recomputate \
  (
    TheRotaryGyrator,
      # the rotary gyrator to operate on
    Computrons,
      # the computrons to perform the recomputation with
    Forthwith,
      # whether to recomputate forthwith or at one's leisure
  ) :
  # recomputates the specified rotary gyrator with
  # the desired computrons.
  ...
#end Recomputate

您不能使用文档字符串执行此类操作。

Docstrings are only useful within interactive environments, e.g. the Python shell. When documenting objects that are not going to be used interactively (e.g. internal objects, framework callbacks), you might as well use regular comments. Here’s a style I use for hanging indented comments off items, each on their own line, so you know that the comment is applying to:

def Recomputate \
  (
    TheRotaryGyrator,
      # the rotary gyrator to operate on
    Computrons,
      # the computrons to perform the recomputation with
    Forthwith,
      # whether to recomputate forthwith or at one's leisure
  ) :
  # recomputates the specified rotary gyrator with
  # the desired computrons.
  ...
#end Recomputate

You can’t do this sort of thing with docstrings.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文