Qual è il modo corretto per documentare un parametro ** kwargs?


99

Sto usando sphinx e il plugin autodoc per generare la documentazione API per i miei moduli Python. Anche se posso vedere come documentare correttamente parametri specifici, non riesco a trovare un esempio di come documentare un **kwargsparametro.

Qualcuno ha un buon esempio di un modo chiaro per documentarli?


Dipende interamente dal metodo docstring che usi. (reStructuredText, Sphinx, Google)
Stevoisiak

2
Questo non avrebbe dovuto essere chiuso. È una domanda valida. È specifico (come documentare ** kwargs usando sphinx) Poiché i commenti ai documenti non sono completamente standardizzati in python, questo si tradurrà in opinioni (o metodi multipli) fintanto che supportano la domanda in modo specifico (sphinx).
JerodG

Risposte:


5

Penso che subprocessi documenti di -module siano un buon esempio. Fornisci un elenco esaustivo di tutti i parametri per una classe principale / genitore . Quindi fai riferimento a quell'elenco per tutte le altre occorrenze di **kwargs.


97
Sono l'unico per cui questa risposta non aveva senso? Non sono riuscito a trovare l'esempio specifico in questione.
Acumenus

2
L'esempio è probabile subprocess.call(*popenargs, **kwargs). È documentato come subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)dove tutto dopo il *è le chiavi riconosciute in **kwargs(o almeno quelle usate frequentemente)
nn

2
La continuazione più significativa di ciò è ora subprocess.Popene non sono sicuro che sia più un esempio particolarmente grandioso.
Donal Fellows

A meno che non mi sbagli, non è più documentato in Python 3.7 .
Mateen Ulhaq

10
Downvoting per non aver incluso un esempio reale nella risposta.
nought101

52

Dopo aver trovato questa domanda, ho deciso quanto segue, che è valido Sphinx e funziona abbastanza bene:

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

    """

La r"""..."""è necessario per rendere questo un docstring "grezza" e mantenere il così \*intatte (per Sphinx far salire come letterale* e non l'inizio di "enfasi").

La formattazione scelta (elenco puntato con tipo tra parentesi e descrizione separata da m-trattini) deve semplicemente corrispondere alla formattazione automatica fornita da Sphinx.

Dopo aver eseguito questo sforzo per rendere la sezione "Argomenti delle parole chiave" simile alla sezione "Parametri" predefinita, sembra che potrebbe essere più semplice eseguire il rollio della sezione dei parametri dall'inizio (come per alcune delle altre risposte) , ma come prova del concetto questo è un modo per ottenere un bell'aspetto per il supplemento **kwargsse stai già usando Sphinx.


26

Docstring di Google Style analizzati da Sphinx

Disclaimer: non testato.

Da questo ritaglio dell'esempio di docstring della sfinge , i *argse **kwargsvengono lasciati non espansi :

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.

Vorrei suggerire la seguente soluzione per la compattezza:

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

Notare come, Optionalnon è richiesto per gli **keyargomenti.

Altrimenti , puoi provare a elencare esplicitamente gli * argomenti sotto Other Parameterse **kwargssotto Keyword Args(vedi sezioni analizzate ):

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

9

C'è un esempio di doctstring per Sphinx nella loro documentazione. Nello specifico mostrano quanto segue:

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

Anche se hai chiesto informazioni esplicitamente, vorrei anche indicare la Guida allo stile di Google Python . Il loro esempio di docstring sembra implicare che non chiamano specificamente kwarg. (other_silly_variable = Nessuno)

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 ha una domanda sulla risposta accettata di fare riferimento alla documentazione di gestione dei sottoprocessi. Se importi un modulo, puoi visualizzare rapidamente le docstrings del modulo tramite inspect.getsource.

Un esempio dell'interprete Python che utilizza la raccomandazione di Silent Ghost:

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

Ovviamente puoi anche visualizzare la documentazione del modulo tramite la funzione di aiuto. Ad esempio aiuto (sottoprocesso)

Personalmente non sono un fan della docstring di sottoprocesso per kwargs come esempio, ma come l'esempio di Google non elenca kwarg separatamente come mostrato nell'esempio della documentazione di 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()

Includo questa risposta alla domanda di ABB perché vale la pena notare che puoi rivedere la fonte o la documentazione di qualsiasi modulo in questo modo per approfondimenti e ispirazione per commentare il tuo codice.


2
Correzione: non fa parte della documentazione di Sphinx, ma di un "progetto pypi di esempio" indipendente, che si descrive esplicitamente come un tutorial non autorevole.
boicottaggio

other_silly_variablenon è un argomento kwargs, ma del tutto normale.
bugmenot123

4

Se qualcun altro sta cercando una sintassi valida .. Ecco un esempio di docstring. È proprio come l'ho fatto, spero ti sia utile, ma non posso affermare che sia conforme a qualcosa in particolare.

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

3
E per quanto riguarda i singoli argomenti delle parole chiave?
maasha

4

Questo dipende dallo stile della documentazione che usi, ma se stai usando lo stile numpydoc si consiglia di documentare **kwargsusando Other Parameters.

Ad esempio, seguendo l'esempio di 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}``.
    """

Nota in particolare che si consiglia di fornire i valori predefiniti di kwargs, poiché questi non sono evidenti dalla firma della funzione.


1
Non sono sicuro che il tuo suggerimento sia tratto da documenti meno recenti o dall'esperienza personale, ma l'attuale documentazione "Altri parametri" (a cui ti colleghi) afferma che dovrebbe essere "usato per descrivere parametri usati di rado" ed è "essere usato solo se una funzione ha un numero elevato di parametri di parole chiave, per evitare di ingombrare la sezione Parametri ".
Ninjakannon

1

Se stai cercando come farlo in stile numpydoc , puoi semplicemente menzionarlo **kwargsnella sezione Parametri senza specificare il tipo , come dimostrato nell'esempio numpydoc dall'estensione sphinx napolean e docstring guide from pandas documentation sprint 2018.

Ecco un esempio che ho trovato dalla guida per sviluppatori LSST che spiega molto bene quale dovrebbe essere la descrizione del **kwargsparametro:

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

In alternativa, basandosi su quanto suggerito da @Jonas Adler, trovo che sia meglio mettere il **kwargse la sua descrizione nella Other Parameterssezione - anche questo esempio dalla guida alla documentazione di matplotlib suggerisce lo stesso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.