Quelle est la manière correcte de documenter un paramètre ** kwargs?

99

J'utilise sphinx et le plugin autodoc pour générer la documentation API pour mes modules Python. Bien que je puisse voir comment documenter joliment des paramètres spécifiques, je ne trouve pas d'exemple sur la façon de documenter un **kwargsparamètre.

Quelqu'un a-t-il un bon exemple d'une manière claire de les documenter?

jkp
la source
Cela dépend entièrement de la méthode docstring que vous utilisez. (reStructuredText, Sphinx, Google)
Stevoisiak
2
Cela n'aurait pas dû être fermé. C'est une question valable. C'est spécifique (comment documenter ** kwargs en utilisant sphinx) Comme les commentaires doc ne sont pas entièrement standardisés en python, cela entraînera des opinions (ou plusieurs méthodes) tant qu'ils supportent la question spécifiquement (sphinx).
JerodG

Réponses:

5

Je pense que subprocessla documentation de -module est un bon exemple. Donnez une liste exhaustive de tous les paramètres d'une classe supérieure / parent . Ensuite, reportez-vous simplement à cette liste pour toutes les autres occurrences de **kwargs.

SilentGhost
la source
97
Suis-je le seul pour qui cette réponse n'avait aucun sens? Je n'ai pas trouvé l'exemple précis en question.
Acumenus
2
L'exemple est probable subprocess.call(*popenargs, **kwargs). Il est documenté comme subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)où tout après le se *trouve les clés reconnues dans **kwargs(Ou du moins celles fréquemment utilisées)
nos
2
La suite la plus significative de cela est maintenant subprocess.Popenet je ne suis pas sûr que ce soit plus un exemple particulièrement excellent.
Donal Fellows
Sauf erreur de ma part, ce n'est plus documenté dans Python 3.7 .
Mateen Ulhaq
10
Voter pour ne pas inclure un exemple réel dans la réponse.
naught101
52

Après avoir trouvé cette question, je me suis installé sur ce qui suit, qui est valide Sphinx et fonctionne assez bien:

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

    """

Le r"""..."""est nécessaire pour en faire une docstring "brute" et ainsi garder la docstring \*intacte (pour que Sphinx le prenne comme un littéral *et non comme le début de "l'emphase").

La mise en forme choisie (liste à puces avec type entre parenthèses et description séparée par m tirets) est simplement pour correspondre à la mise en forme automatisée fournie par Sphinx.

Une fois que vous avez fait l'effort de faire en sorte que la section "Arguments des mots clés" ressemble à la section "Paramètres" par défaut, il semble qu'il pourrait être plus facile de déployer votre propre section de paramètres dès le départ (comme pour certaines des autres réponses) , mais comme preuve de concept, c'est une façon d'obtenir un joli look supplémentaire **kwargssi vous utilisez déjà Sphinx.

quornian
la source
26

Docstrings Google Style analysés par Sphinx

Avertissement: non testé.

À partir de cette découpe de l' exemple de docstring sphinx , les *argset **kwargssont laissés non développés :

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.

Je suggérerais la solution suivante pour la compacité:

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

Remarquez comment, Optionaln'est pas nécessaire pour les **keyarguments.

Sinon , vous pouvez essayer de lister explicitement les * arguments sous Other Parameterset **kwargssous les Keyword Args(voir les sections analysées ):

    """
    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 
        ...
Oleg
la source
9

Il y a un exemple doctstring pour Sphinx dans leur documentation. Plus précisément, ils montrent ce qui suit:

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

Bien que vous ayez posé des questions sur explicitement, je voudrais également pointer vers le guide de style Google Python . Leur exemple docstring semble impliquer qu'ils n'appellent pas spécifiquement les kwargs. (other_silly_variable = Aucun)

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 a une question sur la réponse acceptée consistant à référencer la documentation de gestion des sous-processus. Si vous importez un module, vous pouvez voir rapidement les docstrings du module via inspect.getsource.

Un exemple de l'interpréteur python utilisant la recommandation de Silent Ghost:

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

Bien entendu, vous pouvez également consulter la documentation du module via la fonction d'aide. Par exemple aide (sous-processus)

Je ne suis pas personnellement fan du sous-processus docstring pour kwargs à titre d'exemple, mais comme l'exemple Google, il ne répertorie pas les kwargs séparément, comme indiqué dans l'exemple de documentation Sphinx.

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

J'inclus cette réponse à la question d'ABB, car il convient de noter que vous pouvez consulter la source ou la documentation de n'importe quel module de cette façon pour obtenir des informations et de l'inspiration pour commenter votre code.

substrat binaire
la source
2
Correction: cela ne fait pas partie de la documentation de Sphinx, mais d'un 'exemple de projet pypi' indépendant, qui se décrit explicitement comme un tutoriel ne faisant pas autorité.
boycy
other_silly_variablen'est pas un argument kwargs, mais un argument tout à fait normal.
bugmenot123
4

Si quelqu'un d'autre recherche une syntaxe valide .. Voici un exemple de docstring. C'est comme ça que je l'ai fait, j'espère que cela vous est utile, mais je ne peux pas prétendre que c'est conforme à quoi que ce soit en particulier.

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
m01
la source
3
Alors qu'en est-il des arguments de mots clés individuels?
maasha
4

Cela dépend du style de documentation que vous utilisez, mais si vous utilisez le style numpydoc , il est recommandé de documenter en **kwargsutilisantOther Parameters .

Par exemple, en suivant l'exemple de 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}``.
    """

Notez surtout qu'il est recommandé de donner les valeurs par défaut de kwargs, car celles-ci ne sont pas évidentes à partir de la signature de la fonction.

Jonas Adler
la source
1
Je ne sais pas si votre suggestion est tirée de documents plus anciens ou d'expérience personnelle, mais la documentation actuelle "Autres paramètres" (vers laquelle vous établissez un lien) indique qu'elle devrait être "utilisée pour décrire des paramètres rarement utilisés" et qu'elle "ne doit être utilisée que si une fonction a un grand nombre de paramètres de mots-clés, pour éviter d'encombrer la section Paramètres ".
Ninjakannon le
1

Si vous cherchez comment faire cela dans le style numpydoc , vous pouvez simplement mentionner **kwargsdans la section Paramètres sans spécifier le type - comme illustré dans l' exemple numpydoc de l'extension sphinx napolean et docstring guide de pandas documentation sprint 2018.

Voici un exemple que j'ai trouvé dans le guide du développeur LSST qui explique très bien quelle devrait être la description du **kwargsparamètre:

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

Alternativement, en me basant sur ce que @Jonas Adler a suggéré, je trouve préférable de mettre le **kwargset sa description dans la Other Parameterssection - même cet exemple du guide de documentation matplotlib suggère la même chose.

Jaladh Singhal
la source