关于python:记录** kwargs参数的正确方法是什么?

What is the correct way to document a **kwargs parameter?

我正在使用sphinx和autoDoc插件为我的Python模块生成API文档。虽然我可以看到如何很好地记录特定的参数,但我找不到一个如何记录**kwargs参数的示例。

有没有人有一个很好的清晰的记录方法的例子?


在发现这个问题后,我决定了以下问题,这是有效的斯芬克斯和相当好的工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def some_function(first, second="two", **kwargs):
    r"""Fetches and returns this thing

    :param first:
        The first parameter
    :type first: ``int``
    :param second:
        The second parameter
    :type second: ``str``
    :param \**kwargs:
        See below

    :Keyword Arguments:
        * *extra* (``list``) --
          Extra stuff
        * *supplement* (``dict``) --
          Additional content

   """

要求r"""..."""使其成为"原始"文档字符串,从而保持\*的完整性(以便sphinx作为文字*而不是"强调"的开始)。

所选的格式(带括号类型的项目符号列表和M-dash分隔的描述)只是为了与斯芬克斯提供的自动格式匹配。

一旦你努力使"关键字参数"部分看起来像默认的"参数"部分,似乎从一开始就可以更容易地滚动你自己的参数部分(根据其他一些答案),但是作为概念证明,这是一种很好地寻找补充的**kwargs的方法,如果你是alr用狮身人面像。


我认为subprocess模块的文档就是一个很好的例子。给出顶级/父类的所有参数的详尽列表。然后,只需参考该列表中所有其他出现的**kwargs


Sphinx解析的Google风格文档字符串

免责声明:未测试。

根据狮身人面像docstring示例的切口,*args**kwargs未展开:

1
2
3
4
5
6
7
8
9
10
def module_level_function(param1, param2=None, *args, **kwargs):
   """
    ...

    Args:
        param1 (int): The first parameter.
        param2 (Optional[str]): The second parameter. Defaults to None.
            Second line of description should be indented.
        *args: Variable length argument list.
        **kwargs: Arbitrary keyword arguments.

对于压实度,我建议采用以下解决方案:

1
2
3
4
5
6
7
8
9
10
11
   """
    Args:
        param1 (int): The first parameter.
        param2 (Optional[str]): The second parameter. Defaults to None.
            Second line of description should be indented.
        *param3 (int): description
        *param4 (str):
        ...
        **key1 (int): description
        **key2 (int): description
        ...

注意,**key参数不需要Optional

否则,您可以尝试在Other Parameters**kwargs下明确列出*个参数在Keyword Args下(参见解析部分):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
   """
    Args:
        param1 (int): The first parameter.
        param2 (Optional[str]): The second parameter. Defaults to None.
            Second line of description should be indented.

    Other Parameters:
        param3 (int): description
        param4 (str):
        ...

    Keyword Args:
        key1 (int): description
        key2 (int): description
        ...

在他们的文档中有一个sphinx的doctstring示例。具体来说,它们显示了以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def public_fn_with_googley_docstring(name, state=None):
"""This function does something.

Args:
   name (str):  The name to use.

Kwargs:
   state (bool): Current state to be in.

Returns:
   int.  The return code::

      0 -- Success!
      1 -- No good.
      2 -- Try again.

Raises:
   AttributeError, KeyError

A really great idea.  A way you might use me is

>>> print public_fn_with_googley_docstring(name='foo', state=None)
0

BTW, this always returns 0.  **NEVER** use with :class:`MyPublicClass`.

"""

return 0

虽然您明确地询问了斯芬克斯,但我也会指向Google Python风格指南。他们的docstring示例似乎暗示了他们并没有特别指出Kwarg。(其他变量=无)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
"""Fetches rows from a Bigtable.

Retrieves rows pertaining to the given keys from the Table instance
represented by big_table.  Silly things may happen if
other_silly_variable is not None.

Args:
    big_table: An open Bigtable Table instance.
    keys: A sequence of strings representing the key of each table row
        to fetch.
    other_silly_variable: Another optional variable, that has a much
        longer name than the other args, and which does nothing.

Returns:
    A dict mapping keys to the corresponding table row data
    fetched. Each row is represented as a tuple of strings. For
    example:

    {'Serak': ('Rigel VII', 'Preparer'),
     'Zim': ('Irk', 'Invader'),
     'Lrrr': ('Omicron Persei 8', 'Emperor')}

    If a key from the keys argument is missing from the dictionary,
    then that row was not found in the table.

Raises:
    IOError: An error occurred accessing the bigtable.Table object.
"""

pass

A-B-B对引用子流程管理文档的公认答案有疑问。如果导入模块,可以通过inspect.getsource快速查看模块docstrings。

使用Silent Ghost建议的python解释器示例:

1
2
3
>>> import subprocess
>>> import inspect
>>> import print inspect.getsource(subprocess)

当然,您也可以通过帮助功能查看模块文档。例如帮助(子流程)

我个人并不喜欢以Kwargs为例的子流程docstring,但和Google的例子一样,它不会像sphinx文档示例中所示那样单独列出Kwarg。

1
2
3
4
5
6
7
8
9
def call(*popenargs, **kwargs):
"""Run command with arguments.  Wait for command to complete, then
return the returncode attribute.

The arguments are the same as for the Popen constructor.  Example:

retcode = call(["ls","-l"])
"""

return Popen(*popenargs, **kwargs).wait()

我将这个答案包括在A-B-B的问题中,因为值得注意的是,您可以通过这种方式查看任何模块的源代码或文档,以获得评论代码的洞察力和灵感。


如果其他人正在寻找一些有效的语法..下面是一个docstring示例。我就是这样做的,我希望它对你有用,但我不能声称它符合任何特别的要求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def bar(x=True, y=False):
   """
    Just some silly bar function.

    :Parameters:
      - `x` (`bool`) - dummy description for x
      - `y` (`string`) - dummy description for y
    :return: (`string`) concatenation of x and y.
   """

    return str(x) + y

def foo (a, b, **kwargs):
   """
    Do foo on a, b and some other objects.

    :Parameters:
      - `a` (`int`) - A number.
      - `b` (`int`, `string`) - Another number, or maybe a string.
      - `\**kwargs` - remaining keyword arguments are passed to `bar`

    :return: Success
    :rtype: `bool`
   """

    return len(str(a) + str(b) + bar(**kwargs)) > 20


这取决于您使用的文档的样式,但是如果您使用的是numpydoc样式,建议使用Other Parameters来记录**kwargs

例如,下面是Quornian的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def some_function(first, second="two", **kwargs):
   """Fetches and returns this thing

    Parameters
    ----------
    first : `int`
        The first parameter
    second : `str`, optional
        The second parameter

    Other Parameters
    ----------------
    extra : `list`, optional
        Extra stuff. Default ``[]``.
    suplement : `dict`, optional
        Additional content. Default ``{'key' : 42}``.
   """

特别要注意的是,建议给出Kwargs的默认值,因为这些值在函数签名中并不明显。