Apa cara yang benar untuk mendokumentasikan parameter ** kwargs?

99

Saya menggunakan sphinx dan plugin autodoc untuk menghasilkan dokumentasi API untuk modul Python saya. Meskipun saya dapat melihat cara mendokumentasikan parameter tertentu dengan baik, saya tidak dapat menemukan contoh cara mendokumentasikan **kwargsparameter.

Adakah yang punya contoh bagus tentang cara yang jelas untuk mendokumentasikannya?

jkp
sumber
Ini sepenuhnya bergantung pada metode docstring yang Anda gunakan. (reStructuredText, Sphinx, Google)
Stevoisiak
2
Ini seharusnya tidak ditutup. Ini adalah pertanyaan yang valid. Ini spesifik (bagaimana mendokumentasikan ** kwargs menggunakan sphinx) Karena komentar doc tidak sepenuhnya distandarisasi dalam python, ini akan menghasilkan opini (atau beberapa metode) selama mereka mendukung pertanyaan secara spesifik (sphinx).
JerodG

Jawaban:

4

Saya pikir subprocessdokumen -module adalah contoh yang bagus. Berikan daftar lengkap semua parameter untuk kelas atas / induk . Kemudian lihat saja daftar itu untuk semua kemunculan lainnya **kwargs.

SilentGhost
sumber
98
Apakah saya satu-satunya orang yang jawaban ini tidak masuk akal? Saya tidak dapat menemukan contoh spesifik yang dimaksud.
Acumenus
2
Contohnya mungkin subprocess.call(*popenargs, **kwargs). Itu didokumentasikan sebagai di subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)mana segala sesuatu setelah *adalah kunci yang dikenali di **kwargs(Atau setidaknya yang sering digunakan)
no
2
Kelanjutan yang paling berarti dari itu adalah sekarang subprocess.Popendan saya tidak yakin itu adalah contoh yang sangat bagus lagi.
Donal Fellows
Kecuali saya salah, itu tidak lagi didokumentasikan dengan Python 3.7 .
Mateen Ulhaq
11
Downvoting karena tidak menyertakan contoh aktual dalam jawaban.
n nothing101
52

Setelah menemukan pertanyaan ini, saya memutuskan yang berikut, yang merupakan Sphinx yang valid dan berfungsi dengan cukup baik:

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

    """

The r"""..."""diperlukan untuk membuat ini "mentah" docstring dan dengan demikian menjaga \*utuh (untuk Sphinx untuk mengambil sebagai literal sebuah* dan bukan awal dari "penekanan").

Pemformatan yang dipilih (daftar berpoin dengan jenis tanda kurung dan deskripsi yang dipisahkan m-dash) cukup untuk mencocokkan pemformatan otomatis yang disediakan oleh Sphinx.

Setelah Anda melakukan upaya untuk membuat bagian "Argumen Kata Kunci" terlihat seperti bagian "Parameter" default, sepertinya akan lebih mudah untuk menggulirkan bagian parameter Anda sendiri dari awal (sesuai dengan beberapa jawaban lainnya) , tetapi sebagai bukti konsep, ini adalah salah satu cara untuk mendapatkan tampilan tambahan yang bagus **kwargsjika Anda sudah menggunakan Sphinx.

quornian
sumber
26

Docstring Google Style diurai oleh Sphinx

Penafian: tidak diuji.

Dari potongan contoh dokumen sphinx ini , *argsdan **kwargsdibiarkan tidak diperluas :

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.

Saya akan menyarankan solusi berikut untuk kekompakan:

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

Perhatikan bagaimana, Optionaltidak diperlukan untuk **keyargumen.

Jika tidak , Anda dapat mencoba mencantumkan * args secara eksplisit di bawah Other Parametersdan di **kwargsbawah Keyword Args(lihat bagian yang diurai ):

    """
    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
sumber
9

Ada contoh doctstring untuk Sphinx dalam dokumentasinya. Secara khusus mereka menunjukkan yang berikut:

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

Meskipun Anda bertanya tentang secara eksplisit, saya juga akan menunjuk ke Panduan Gaya Google Python . Contoh docstring mereka tampaknya menyiratkan bahwa mereka tidak menyebut kwarg secara khusus. (variabel_lain = Tidak ada)

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 memiliki pertanyaan tentang jawaban yang diterima dari referensi dokumentasi manajemen subproses. Jika Anda mengimpor modul, Anda dapat dengan cepat melihat modul docstrings melalui inspect.getsource.

Contoh dari interpreter python menggunakan rekomendasi Silent Ghost:

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

Tentu saja Anda juga dapat melihat dokumentasi modul melalui fungsi bantuan. Misalnya bantuan (subproses)

Saya pribadi bukan penggemar subproses docstring untuk kwargs sebagai contoh, tetapi seperti contoh Google itu tidak mencantumkan kwargs secara terpisah seperti yang ditunjukkan dalam contoh dokumentasi 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()

Saya menyertakan jawaban ini untuk pertanyaan ABB karena perlu dicatat bahwa Anda dapat meninjau sumber atau dokumentasi modul apa pun dengan cara ini untuk mendapatkan wawasan dan inspirasi untuk mengomentari kode Anda.

biner substrat
sumber
2
Koreksi: itu bukan bagian dari dokumentasi Sphinx, tapi dari 'contoh proyek pypi' independen, yang secara eksplisit mendeskripsikan dirinya sebagai tutorial non-otoritatif.
boycy
other_silly_variablebukanlah argumen kwargs, tetapi argumen yang sepenuhnya normal.
bugmenot123
4

Jika ada orang lain yang mencari sintaks yang valid .. Berikut adalah contoh docstring. Beginilah cara saya melakukannya, saya harap ini berguna bagi Anda, tetapi saya tidak dapat mengklaim bahwa ini sesuai dengan apa pun secara khusus.

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
sumber
3
Jadi bagaimana dengan argumen kata kunci individual?
maasha
4

Ini tergantung pada gaya dokumentasi yang Anda gunakan, tetapi jika Anda menggunakan gaya numpydoc , disarankan untuk **kwargsmenggunakan dokumen Other Parameters.

Misalnya, mengikuti contoh 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}``.
    """

Perhatikan terutama bahwa disarankan untuk memberikan default kwargs, karena ini tidak jelas dari tanda tangan fungsi.

Jonas Adler
sumber
1
Saya tidak yakin apakah saran Anda diambil dari dokumen lama atau pengalaman pribadi, tetapi dokumentasi "Parameter Lain" saat ini (yang Anda tautkan) menyatakan bahwa itu harus "digunakan untuk menjelaskan parameter yang jarang digunakan" dan "hanya digunakan jika suatu fungsi memiliki banyak parameter kata kunci, untuk mencegah kekacauan pada bagian Parameter ".
Ninjakannon
1

Jika Anda mencari cara melakukan ini dengan gaya numpydoc , Anda cukup menyebutkannya **kwargsdi bagian Parameter tanpa menentukan jenisnya - seperti yang ditunjukkan dalam contoh numpydoc dari napolean ekstensi sphinx dan panduan docstring dari pandas dokumentasi sprint 2018.

Berikut ini adalah contoh yang saya temukan dari LSST panduan pengembang yang sangat baik menjelaskan apa yang seharusnya menjadi deskripsi dari **kwargsparameter:

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

Atau, berdasarkan saran @Jonas Adler, saya merasa lebih baik untuk meletakkan **kwargsdan deskripsinya di Other Parametersbagian - bahkan contoh dari panduan dokumentasi matplotlib ini menyarankan hal yang sama.

Jaladh Singhal
sumber