Как правильно задокументировать параметр ** kwargs?

99

Я использую sphinx и плагин autodoc для создания документации API для моих модулей Python. Хотя я вижу, как красиво документировать определенные параметры, я не могу найти пример того, как документировать **kwargsпараметр.

Есть ли у кого-нибудь хороший пример четкого способа их документировать?

jkp
источник
Это полностью зависит от того, какой метод строки документации вы используете. (reStructuredText, Sphinx, Google)
Stevoisiak 07
2
Это не должно было быть закрыто. Это правильный вопрос. Это специфично (как документировать ** kwargs с помощью sphinx). Поскольку комментарии к документам не полностью стандартизированы в python, это приведет к мнениям (или нескольким методам), если они поддерживают вопрос конкретно (sphinx).
JerodG

Ответы:

4

Я думаю, что subprocess-module docs - хороший пример. Дайте исчерпывающий список всех параметров для верхнего / родительского класса . Тогда просто обратитесь к этому списку для всех остальных случаев **kwargs.

Тихий призрак
источник
98
Я единственный, для кого этот ответ не имел смысла? Я не смог найти конкретный рассматриваемый пример.
Acumenus
2
Пример вероятен subprocess.call(*popenargs, **kwargs). В документации subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)указано, что все, что *находится после символа, является распознанными ключами в **kwargs(или, по крайней мере, теми, которые часто используются)
2
Наиболее значимым продолжением этого является сейчас, subprocess.Popenи я не уверен, что это сейчас особенно хороший пример.
Donal Fellows
Если я не ошибаюсь, это больше не документировано в Python 3.7 .
Mateen Ulhaq 01
11
Голосование против не включения в ответ фактического примера.
naught101 05
52

Найдя этот вопрос, я остановился на следующем, что является действительным 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"""..."""Требуется , чтобы сделать это «сырой» и , таким образом , строка документации держать\* нетронутыми (для Сфинкса , чтобы забрать в качестве литерала* , а не в начале «упор»).

Выбранное форматирование (маркированный список с типом в скобках и описанием, разделенным m-тире) просто соответствует автоматическому форматированию, предоставляемому Sphinx.

После того, как вы приложили усилия, чтобы раздел «Аргументы ключевого слова» выглядел как раздел «Параметры» по умолчанию, кажется, что может быть проще с самого начала развернуть свой собственный раздел параметров (согласно некоторым другим ответам) , но в качестве доказательства концепции это один из способов добиться красивого внешнего вида дополнительных, **kwargsесли вы уже используете Sphinx.

Quornian
источник
26

Строки документации Google Style, проанализированные Sphinx

Отказ от ответственности: не проверено.

Из этого вырезанного примера строки документации sphinx , *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под 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 
        ...
Олег
источник
9

В их документации есть пример doctstring для Sphinx. В частности, они показывают следующее:

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 . Их пример со строкой документации, кажется, подразумевает, что они не вызывают специально kwargs. (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 в качестве примера, но, как и в примере Google, он не перечисляет kwargs отдельно, как показано в примере документации 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()

Я включаю этот ответ на вопрос ABB, потому что стоит отметить, что вы можете просмотреть исходный код любого модуля или документацию таким образом, чтобы получить идеи и вдохновение для комментирования вашего кода.

бинарный субстрат
источник
2
Исправление: это не часть документации Sphinx, а независимый «пример проекта pypi», который явно описывает себя как неавторитетный учебник.
boycy
other_silly_variableэто не аргумент Кваргса, а вполне нормальный.
bugmenot123
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
m01
источник
3
Так что насчет отдельных аргументов ключевого слова?
maasha
4

Это зависит от стиля документации, который вы используете, но если вы используете стиль numpydoc , рекомендуется документировать **kwargsиспользование Other Parameters.

Например, следующий пример Куорниана:

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, поскольку они не очевидны из сигнатуры функции.

Йонас Адлер
источник
1
Я не уверен, основано ли ваше предложение на более старых документах или на личном опыте, но в текущей документации «Другие параметры» (на которую вы ссылаетесь) указано, что ее следует «использовать для описания редко используемых параметров» и «использовать только если функция имеет большое количество параметров ключевого слова, чтобы не загромождать раздел параметров ».
Ниндзяканнон,
1

Если вы ищете, как это сделать в стиле numpydoc , вы можете просто указать **kwargsв разделе параметров без указания типа - как показано в примере numpydoc из наполеона расширения sphinx и руководства по строкам документации из спринта документации pandas 2018.

Вот пример , который я нашел из 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 предполагает то же самое.

Джалад Сингхал
источник