10

So, I've found posts related to other styles and I am aware of this NumPy page about the documentation but I am confused. I didn't understand how to add each kwargs to the parameters section of a method. This is from the given web page:

def foo(var1, var2, *args, long_var_name='hi', **kwargs):
    r"""Summarize the function in one line.

    Several sentences providing an extended description. Refer to
    variables using back-ticks, e.g. `var`.

    Parameters
    ----------
    var1 : array_like
        Array_like means all those objects -- lists, nested lists, etc. --
        that can be converted to an array.  We can also refer to
        variables like `var1`.
    var2 : int
        The type above can either refer to an actual Python type
        (e.g. ``int``), or describe the type of the variable in more
        detail, e.g. ``(N,) ndarray`` or ``array_like``.
    *args : iterable
        Other arguments.
    long_var_name : {'hi', 'ho'}, optional
        Choices in brackets, default first when optional.
    **kwargs : dict
        Keyword arguments.

It is not clear how to add each kwargs here. I also saw this sphinx page "Example NumPy Style Python Docstring", here is the section about the kwargs:

def module_level_function(param1, param2=None, *args, **kwargs):
    """This is an example of a module level function.

    Function parameters should be documented in the ``Parameters`` section.
    The name of each parameter is required. The type and description of each
    parameter is optional, but should be included if not obvious.

    If \*args or \*\*kwargs are accepted,
    they should be listed as ``*args`` and ``**kwargs``.

    The format for a parameter is::

        name : type
            description

            The description may span multiple lines. Following lines
            should be indented to match the first line of the description.
            The ": type" is optional.

            Multiple paragraphs are supported in parameter
            descriptions.

    Parameters
    ----------
    param1 : int
        The first parameter.
    param2 : :obj:`str`, optional
        The second parameter.
    *args
        Variable length argument list.
    **kwargs
        Arbitrary keyword arguments. 

Nope, I am still confused. Is it something like this?

"""
Dummy docstring.

Parameters
----------
**kwargs: dict
    first_kwarg: int
        This is an integer
    second_kwarg: str
        This is a string
"""
MehmedB
  • 1,059
  • 1
  • 16
  • 42
  • 4
    I have puzzled over this question myself and still don't have a great answer. On the other hand, I have also thought the following: if a specific `kwargs` key is important enough to document, perhaps I should elevate it to being a proper named keyword argument in the function signature. Something to consider. – FMc Jun 22 '20 at 09:25
  • In my experiment, need to define it first if you wanna use it. `kwargs.pop('name_var', value)` – CuCaRot Jun 22 '20 at 09:53
  • You can [search for examples](https://www.google.com/search?q=%22kwargs%22+site%3Anumpy.org%2Fdoc%2Fstable%2Freference%2Fgenerated) but it seems to vary. [Ufuncs](https://numpy.org/doc/stable/reference/generated/numpy.equal.html) have their own kwargs docs, some [defer you to other docs](https://numpy.org/doc/stable/reference/generated/numpy.apply_along_axis.html), some [ignore it](https://numpy.org/doc/stable/reference/generated/numpy.ma.stack.html), some just [list them as if they were in the signature](https://numpy.org/doc/stable/reference/generated/numpy.meshgrid.html)... – jdehesa Jun 22 '20 at 10:22
  • For inspiration, you can look at other APIs, for example [Matplotlib](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html), which makes extensive use of kwargs (Matplotlib docs system seems to be rather complicated, I think the property tables are rendered at HTML level, but the docstring is just a list of indented items generated through introspection). – jdehesa Jun 22 '20 at 10:26
  • Your first link ("this") is a 404. I _believe_ you meant to put https://numpy.org/devdocs/dev/howto-docs.html instead of https://numpy.org/devdocs/docs/howto_document.html#a-guide-to-numpy-scipy-documentation (The anchor isn't necessary, as that's the top of the page.) – Chris Larson Feb 06 '22 at 19:02

2 Answers2

9

Summary

The **kwargs are not typically listed in the function, but instead the final destination of the **kwargs is mentioned. For example:

**kwargs
    Instructions on how to decorate your plots.
    The keyword arguments are passed to `matplotlib.axes.Axes.plot()` 
  • If there are multiple possible targets, they are all listed (see below)
  • If you happen to use some automation tool to interpolate and link your documentation, then you might list the possible keyword arguments in **kwargs for the convenience of the end users. This kind of approach is used in matplotlib, for example. (see below)

How and when document **kwargs (Numpydoc)

1) When to use **kwargs?

First thing to note here is that **kwargs should be used to pass arguments to underlying functions and methods. If the argument inside **kwargs would be used in the function (and not passed down), it should be written out as normal keyword argument, instead.

2) Where to put **kwargs decription?

The location of **kwargs description is in the Parameters section. Sometimes it is appropriate to list them in the Other Parameters section, but remember: Other Parameters should only be used if a function has a large number of keyword parameters, to prevent cluttering the Parameters section.

  • matplotlib.axes.Axes.grid has **kwargs in Parameters section.
  • matplotlib.axes.Axes.plot has **kwargs in Other Parameters section (reasoning probably to large number of keyword arguments).

3) Syntax for **kwargs decription

The syntax for the description for the **kwargs is, following Numpydoc styleguide

Parameters
----------
... (other lines)
**kwargs : sometype
     Some description on what the kwargs are
     used for.

or

Parameters
----------
... (other lines)
**kwargs
     Some description on what the kwargs are
     used for.

The one describing the type is more appropriate, as [source].

For the parameter types, be as precise as possible

One exception for this is for example when the **kwargs could be passed to one of many functions based on other parameter values, as in seaborn.kdeplot. Then, the line for the type would become too long for describing all the types and it would be cleaner to use a bullet point list, which also describes the conditions on when the **kwargs are forwarded to where. Eg.:

Parameters
----------
fill: bool or None
    If True, fill in the area under univariate density curves or between 
     bivariate contours. If None, the default depends on multiple.
**kwargs
    Other keyword arguments are passed to one of the following matplotlib 
    functions:

    * matplotlib.axes.Axes.plot() (univariate, fill=False),

    * matplotlib.axes.Axes.fill_between() (univariate, fill=True),

    * matplotlib.axes.Axes.contour() (bivariate, fill=False),

    * matplotlib.axes.contourf() (bivariate, fill=True).

You may also add listing of the valid keyword arguments in **kwargs like in matplotlib.axes.Axes.grid. Here is the interpolated python doc/text version:

Parameters
----------
... (other lines)
**kwargs : `.Line2D` properties
    Define the line properties of the grid, e.g.::

        grid(color='r', linestyle='-', linewidth=2)

    Valid keyword arguments are:

    Properties:
    agg_filter: a filter function, which takes a (m, n, 3) float array and a dpi value, and returns a (m, n, 3) array
    alpha: float or None
    animated: bool
    antialiased or aa: bool
    clip_box: `.Bbox`
    clip_on: bool
    clip_path: Patch or (Path, Transform) or None
    color or c: color
    contains: unknown
    dash_capstyle: {'butt', 'round', 'projecting'}
    dash_joinstyle: {'miter', '
    ... (more lines)

This is convenient for the user, but challenging for the developer. In matplotlib this kind of luxury is made possible with the automatization using some special documentation decorators and linking1. Manual writing of allowed kwargs will surely become a code maintenance nightmare.

4) Notes related to **kwargs / Extended help

Some additional info about the **kwargs could be included in the Notes section. For example matplotlib.axes.Axes.plot discusses marker styles, line styles and colors in the Notes section. [2]


[1] They use a @docstring.dedent_interpd decorator which pulls the meaning of the kwargs to the final docs. So that is happening in place of %(Line2D:kwdoc)s, for example.
[2] See: help(ax.plot) where ax is instance of matplotlib.axes.Axes.

Niko Föhr
  • 28,336
  • 10
  • 93
  • 96
6

Usually kwargs that need to be described in the Parameters section would typically be handled like other named arguments and the **kwargs is left unexpanded. However, the numpy style guide also has an Other Parameters section than can be used for providing descriptions of kwargs without cluttering the Parameters section. The style guide describes it as:

An optional section used to describe infrequently used parameters. It should only be used if a function has a large number of keyword parameters, to prevent cluttering the Parameters section.

The numpydoc repo gives this example:

"""

    Other Parameters
    ----------------
    only_seldom_used_keyword : int, optional
        Infrequently used parameters can be described under this optional
        section to prevent cluttering the Parameters section.
    **kwargs : dict
        Other infrequently used keyword arguments. Note that all keyword
        arguments appearing after the first parameter specified under the
        Other Parameters section, should also be described under this
        section.

"""

So, the additional kwargs could be added as

"""

    Other Parameters
    ----------------
    first_kwarg: int
        This is an integer
    second_kwarg: str
        This is a string
    **kwargs : dict
        Other infrequently used keyword arguments.

"""
A Kruger
  • 2,289
  • 12
  • 17
  • 1
    This answer is OK: if you know the keyword on the param, it should be listed at the end of positional params. `**kwargs` is for all the other stuff, like params that will be forwarded. – azelcer Feb 09 '22 at 18:30
  • 1
    Yeah, that's what I say in the first sentence, but offer the `Other Parameters` as an alternative to keep from cluttering the `Parameters` section. – A Kruger Feb 09 '22 at 18:32