Jaki jest prawidłowy sposób udokumentowania parametru ** kwargs?

99

Używam sphinx i wtyczki autodoc do generowania dokumentacji API dla moich modułów Pythona. Chociaż mogę zobaczyć, jak ładnie udokumentować określone parametry, nie mogę znaleźć przykładu, jak udokumentować **kwargsparametr.

Czy ktoś ma dobry przykład jasnego sposobu ich udokumentowania?

jkp
źródło
Zależy to całkowicie od używanej metody docstringowej. (reStructuredText, Sphinx, Google)
Stevoisiak
2
To nie powinno być zamknięte. To ważne pytanie. Jest specyficzny (jak udokumentować ** kwargs przy użyciu sphinx). Ponieważ komentarze do dokumentów nie są w pełni ustandaryzowane w Pythonie, spowoduje to pojawienie się opinii (lub wielu metod), o ile będą one konkretnie wspierać pytanie (sphinx).
JerodG

Odpowiedzi:

4

Myślę, że subprocessdokumentacja -module jest dobrym przykładem. Podaj wyczerpującą listę wszystkich parametrów dla klasy nadrzędnej / nadrzędnej . Następnie odnieś się do tej listy dla wszystkich innych wystąpień **kwargs.

SilentGhost
źródło
98
Czy jestem jedynym, dla którego ta odpowiedź nie miała sensu? Nie udało mi się znaleźć konkretnego przykładu.
Acumenus,
2
Przykład jest prawdopodobny subprocess.call(*popenargs, **kwargs). Udokumentowano, że subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)wszystko po tym *jest rozpoznawanymi kluczami **kwargs(lub przynajmniej tymi często używanymi)
nr
2
Najbardziej znacząca kontynuacja tego jest teraz subprocess.Popeni nie jestem pewien, czy jest to już szczególnie wspaniały przykład.
Donal Fellows
O ile się nie mylę, nie jest to już udokumentowane w Pythonie 3.7 .
Mateen Ulhaq
11
Głosowanie za brakiem rzeczywistego przykładu w odpowiedzi.
naught101
52

Po znalezieniu tego pytania zdecydowałem się na następujący, który jest prawidłowym Sfinksem i działa dość dobrze:

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

    """

Wymagane r"""..."""jest, aby uczynić to „surowym” dokumentem, a tym samym zachować \*nienaruszony (aby Sphinx odebrał jako dosłowne, *a nie początek „podkreślenia”).

Wybrane formatowanie (lista wypunktowana z typem w nawiasach i opisem oddzielonym m-myślnikami) ma po prostu pasować do automatycznego formatowania zapewnianego przez Sphinx.

Po wykonaniu tych starań, aby sekcja „Argumenty słów kluczowych” wyglądała jak domyślna sekcja „Parametry”, wydaje się, że może być łatwiejsze wprowadzenie własnej sekcji parametrów od samego początku (jak w przypadku niektórych innych odpowiedzi) , ale jako dowód słuszności koncepcji jest to jeden ze sposobów na uzyskanie ładnego wyglądu uzupełniającego, **kwargsjeśli już używasz Sphinx.

quornian
źródło
26

Dokumenty w stylu Google przeanalizowane przez Sphinx

Zastrzeżenie: nie testowano.

Z tego wycięcia w przykładzie z dokumentacją sfinksa , *argsi **kwargspozostają nierozwinięte :

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.

Ja proponuję następujące rozwiązanie dla zwartości:

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

Zwróć uwagę, jak Optionalnie jest wymagane w przypadku **keyargumentów.

W przeciwnym razie możesz spróbować jawnie wymienić argumenty * pod Other Parametersi **kwargspod Keyword Args(zobacz przeanalizowane sekcje ):

    """
    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
źródło
9

W ich dokumentacji znajduje się przykładowy dokument dotyczący Sphinx. W szczególności przedstawiają następujące:

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

Chociaż pytałeś o wyraźnie wskazałbym również na przewodnik Google Python Style Guide . Ich przykładowy dokument wydaje się sugerować, że nie odwołują się one konkretnie do kwargs. (other_silly_variable = Brak)

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 ma pytanie o akceptowaną odpowiedź dotyczącą odniesienia do dokumentacji zarządzania podprocesem. Jeśli importujesz moduł, możesz szybko wyświetlić dokumentację modułu za pośrednictwem inspect.getsource.

Przykład z interpretera Pythona korzystającego z rekomendacji Silent Ghost:

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

Oczywiście możesz również przeglądać dokumentację modułu za pomocą funkcji pomocy. Na przykład pomoc (podproces)

Osobiście nie jestem fanem podprocesu docstring dla kwargs jako przykładu, ale podobnie jak przykład Google nie wyświetla osobno kwargów, jak pokazano w przykładzie dokumentacji 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()

Dołączam tę odpowiedź na pytanie ABB, ponieważ warto zauważyć, że w ten sposób możesz przejrzeć źródła lub dokumentację dowolnego modułu, aby uzyskać wgląd i inspirację do komentowania swojego kodu.

binarysubstrate
źródło
2
Poprawka: to nie jest część dokumentacji Sphinx, ale niezależnego „przykładowego projektu pypi”, który wyraźnie określa się jako nieautorytatywny samouczek.
boycy
other_silly_variablenie jest argumentem kwargs, ale całkowicie normalnym.
bugmenot123
4

Jeśli ktoś szuka poprawnej składni… Oto przykładowy ciąg dokumentów. Tak właśnie to zrobiłem, mam nadzieję, że jest to przydatne dla Ciebie, ale nie mogę twierdzić, że jest zgodne z niczym szczególnym.

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
źródło
3
A co z poszczególnymi argumentami słów kluczowych?
maasha
4

Zależy to od stylu używanej dokumentacji, ale jeśli używasz stylu numpydoc , zaleca się dokumentowanie **kwargsza pomocą Other Parameters.

Na przykład, idąc za przykładem Quorniana:

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

Zwróć szczególną uwagę, że zalecane jest podanie wartości domyślnych kwargs, ponieważ nie są one oczywiste z sygnatury funkcji.

Jonas Adler
źródło
1
Nie jestem pewien, czy Twoja sugestia pochodzi ze starszych dokumentów, czy z własnego doświadczenia, ale aktualna dokumentacja „Inne parametry” (do której podajesz odnośnik) stwierdza, że ​​powinna ona być „używana do opisywania rzadko używanych parametrów” i jest „używana tylko jeśli funkcja ma dużą liczbę parametrów słów kluczowych, aby zapobiec zaśmiecaniu sekcji Parametry ”.
Ninjakannon
1

Jeśli szukasz, jak to zrobić w stylu numpydoc , możesz po prostu wspomnieć **kwargsw sekcji Parametry bez określania typu - jak pokazano na przykładzie numpydoc z rozszerzenia sphinx napolean i przewodnika docstring z dokumentacji pandy sprint 2018.

Oto przykład znalazłem z przewodnikiem programisty Godzina ostatniej który bardzo dobrze wyjaśnia, co powinno być opis z **kwargsparametrem:

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

Alternatywnie, opierając się na tym, co zasugerował @Jonas Adler, uważam, że lepiej jest umieścić **kwargsopis i jego opis w Other Parameterssekcji - nawet ten przykład z przewodnika dokumentacji matplotlib sugeruje to samo.

Jaladh Singhal
źródło