记录** kwargs参数的正确方法是什么?

问题:记录** kwargs参数的正确方法是什么?

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

有没有人有一个很好的例子来记录这些问题?

I’m using sphinx and the autodoc plugin to generate API documentation for my Python modules. Whilst I can see how to nicely document specific parameters, I cannot find an example of how to document a **kwargs parameter.

Does anyone have a good example of a clear way to document these?


回答 0

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

I think subprocess-module’s docs is a good example. Give an exhaustive list of all parameters for a top/parent class. Then just refer to that list for all other occurrences of **kwargs.


回答 1

找到这个问题后,我决定使用以下内容,它是有效的Sphinx,效果很好:

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提供的自动格式匹配。

一旦完成了使“关键字参数”部分看起来像默认的“参数”部分的工作,从一开始就似乎可以更轻松地滚动自己的参数部分(根据其他一些答案) ,但作为概念证明,**kwargs如果您已经在使用Sphinx,则这是一种使辅助外观更好看的方法。

After finding this question I settled on the following, which is valid Sphinx and works fairly well:

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

    """

The r"""...""" is required to make this a “raw” docstring and thus keep the \* intact (for Sphinx to pick up as a literal * and not the start of “emphasis”).

The chosen formatting (bulleted list with parenthesized type and m-dash-separated description) is simply to match the automated formatting provided by Sphinx.

Once you’ve gone to this effort of making the “Keyword Arguments” section look like the default “Parameters” section, it seems like it might be easier to roll your own parameters section from the outset (as per some of the other answers), but as a proof of concept this is one way to achieve a nice look for supplementary **kwargs if you’re already using Sphinx.


回答 2

Sphinx解析的Google Style文档字符串

免责声明:未经测试。

sphinx docstring示例的此切口中,*args**kwargs保持未展开状态

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.

建议使用以下紧凑性解决方案:

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

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

否则,您可以尝试在下方Other Parameters**kwargs下方显式列出* args Keyword Args(请参阅解析的部分):

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

Google Style docstrings parsed by Sphinx

Disclaimer: not tested.

From this cutout of the sphinx docstring example, the *args and **kwargs are left unexpanded:

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.

I would suggest the following solution for compactness:

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

Notice how, Optional is not required for **key arguments.

Otherwise, you can try to explicitly list the *args under Other Parameters and **kwargs under the Keyword Args (see parsed sections):

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

回答 3

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

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样式指南。他们的文档字符串示例似乎暗示着他们没有特别指出kwarg。(other_silly_variable =无)

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

ABB有一个关于接受子流程管理文档的可接受答案的问题。如果导入模块,则可以通过inspect.getsource快速查看模块文档字符串。

python解释器中使用Silent Ghost推荐的示例:

>>> import subprocess
>>> import inspect
>>> import print inspect.getsource(subprocess)

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

我个人不喜欢kwargs的子进程docstring,但是像Google的例子一样,它不会像Sphinx文档示例中那样单独列出kwargs。

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()

我之所以要回答ABB的问题,是因为值得注意的是,您可以以这种方式查看任何模块的源代码或文档,以获取洞察力和注释代码的灵感。

There is a doctstring example for Sphinx in their documentation. Specifically they show the following:

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

Though you asked about explicitly, I would also point to the Google Python Style Guide. Their docstring example seems to imply that they don’t call out kwargs specifically. (other_silly_variable=None)

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 has a question about the accepted answer of referencing the subprocess management documentation. If you import a module, you can quickly see the module docstrings via inspect.getsource.

An example from the python interpreter using Silent Ghost’s recommendation:

>>> import subprocess
>>> import inspect
>>> import print inspect.getsource(subprocess)

Of course you can also view the module documentation via help function. For example help(subprocess)

I’m not personally a fan of the subprocess docstring for kwargs as an example, but like the Google example it doesn’t list kwargs seperately as shown in the Sphinx documentation example.

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()

I’m including this answer to A-B-B’s question because it’s worth noting that you can review any module’s source or documentation this way for insights and inspiration for commenting your code.


回答 4

如果还有其他人正在寻找一些有效的语法。.这是一个示例文档字符串。这就是我所做的,我希望它对您有用,但是我不能断言它特别符合任何要求。

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

If anyone else is looking for some valid syntax.. Here’s an example docstring. This is just how I did it, I hope it’s useful to you, but I can’t claim that it’s compliant with anything in particular.

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

回答 5

这取决于你使用的文档的风格,但如果您使用的是numpydoc风格则建议记录**kwargs使用Other Parameters

例如,遵循quornian的示例:

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的默认值,因为这些默认值在函数签名中并不明显。

This depends on the style of documentation you use, but if you are using the numpydoc style it is recommend to document **kwargs using Other Parameters.

For example, following quornian’s example:

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}``.
    """

Note especially that it is recommended to give the defaults of kwargs, since these are not obvious from the function signature.


回答 6

如果您正在寻找如何以numpydoc样式执行此操作,则可以仅在Parameters部分中提及**kwargs而无需指定类型 -如pandas文档sprint 2018 的sphinx扩展napolean和docstring指南中的numpydoc示例所示

下面是我从发现一个例子的LSST开发人员指南这很好解释了什么是应该是描述**kwargs参数:

def demoFunction(namedArg, *args, flag=False, **kwargs):
    """Demonstrate documentation for additional keyword and
    positional arguments.

    Parameters
    ----------
    namedArg : `str`
        A named argument that is documented like always.
    *args : `str`
        Additional names.

        Notice how the type is singular since the user is expected to pass individual
        `str` arguments, even though the function itself sees ``args`` as an iterable
        of `str` objects).
    flag : `bool`
        A regular keyword argument.
    **kwargs
        Additional keyword arguments passed to `otherApi`.

        Usually kwargs are used to pass parameters to other functions and
        methods. If that is the case, be sure to mention (and link) the
        API or APIs that receive the keyword arguments.

        If kwargs are being used to generate a `dict`, use the description to
        document the use of the keys and the types of the values.
    """

另外,在@Jonas Adler的建议的基础上,我发现最好**kwargs其及其描述放在本Other Parameters节中 -即使是matplotlib文档指南中的示例也表明了这一点

If you are looking for how to do this in numpydoc style, you can simply mention **kwargs in Parameters section without specifying type – as demonstrated in numpydoc example from the sphinx extension napolean and docstring guide from pandas documentation sprint 2018.

Here’s an example I found from LSST developer guide which very well explains what should be the description of **kwargs parameter:

def demoFunction(namedArg, *args, flag=False, **kwargs):
    """Demonstrate documentation for additional keyword and
    positional arguments.

    Parameters
    ----------
    namedArg : `str`
        A named argument that is documented like always.
    *args : `str`
        Additional names.

        Notice how the type is singular since the user is expected to pass individual
        `str` arguments, even though the function itself sees ``args`` as an iterable
        of `str` objects).
    flag : `bool`
        A regular keyword argument.
    **kwargs
        Additional keyword arguments passed to `otherApi`.

        Usually kwargs are used to pass parameters to other functions and
        methods. If that is the case, be sure to mention (and link) the
        API or APIs that receive the keyword arguments.

        If kwargs are being used to generate a `dict`, use the description to
        document the use of the keys and the types of the values.
    """

Alternatively, building upon what @Jonas Adler suggested, I find it better to put the **kwargs and its description in Other Parameters section – even this example from matplotlib documentation guide suggests the same.