วิธีที่ถูกต้องในการบันทึกพารามิเตอร์ ** kwargs คืออะไร


102

ฉันใช้สฟิงซ์และปลั๊กอิน autodoc เพื่อสร้างเอกสาร API สำหรับโมดูล Python ของฉัน ในขณะที่ฉันสามารถดูวิธีจัดทำเอกสารพารามิเตอร์เฉพาะได้อย่างสวยงาม แต่ฉันไม่พบตัวอย่างวิธีการจัดทำเอกสาร**kwargsพารามิเตอร์

ใครมีตัวอย่างวิธีที่ชัดเจนในการจัดทำเอกสารเหล่านี้บ้าง?


สิ่งนี้ขึ้นอยู่กับวิธีการ docstring ที่คุณใช้ (reStructuredText, Sphinx, Google)
Stevoisiak

2
สิ่งนี้ไม่ควรถูกปิด เป็นคำถามที่ถูกต้อง เป็นเรื่องเฉพาะ (วิธีการจัดทำเอกสาร ** kwargs โดยใช้ sphinx) เนื่องจากความคิดเห็นของ doc ไม่ได้เป็นมาตรฐานทั้งหมดใน python สิ่งนี้จะส่งผลให้เกิดความคิดเห็น (หรือหลายวิธี) ตราบใดที่พวกเขาสนับสนุนคำถามโดยเฉพาะ (สฟิงซ์)
JerodG

คำตอบ:


3

ฉันคิดว่าsubprocess- เอกสารของโมดูลเป็นตัวอย่างที่ดี ให้รายการครบถ้วนสมบูรณ์ของพารามิเตอร์ทั้งหมดสำหรับชั้นบนแม่ / แล้วก็หมายถึงรายการที่เกิดขึ้นอื่น ๆ **kwargsทั้งหมดของ


100
ฉันเป็นคนเดียวที่คำตอบนี้ไม่สมเหตุสมผลหรือไม่? ฉันไม่พบตัวอย่างที่เป็นปัญหา
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

12
การลงคะแนนโดยไม่รวมตัวอย่างจริงในคำตอบ
naught101

53

หลังจากพบคำถามนี้ฉันได้ตัดสินสิ่งต่อไปนี้ซึ่งเป็นสฟิงซ์ที่ถูกต้องและทำงานได้ดีพอสมควร:

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"""..."""จะต้องทำเรื่องนี้ให้เป็น "ดิบ" docstring จึงให้\*เหมือนเดิม (สำหรับสฟิงซ์จะหยิบขึ้นมาเป็นตัวอักษร*และไม่ได้เริ่มต้นของ "เน้นที่")

การจัดรูปแบบที่เลือก (รายการสัญลักษณ์แสดงหัวข้อย่อยที่มีประเภทในวงเล็บและคำอธิบายที่คั่นด้วยเครื่องหมาย m) เป็นเพียงเพื่อให้ตรงกับการจัดรูปแบบอัตโนมัติที่ Sphinx ให้มา

เมื่อคุณพยายามทำให้ส่วน "อาร์กิวเมนต์คำหลัก" ดูเหมือนส่วน "พารามิเตอร์" เริ่มต้นแล้วดูเหมือนว่าการม้วนส่วนพารามิเตอร์ของคุณเองตั้งแต่แรกอาจจะง่ายกว่า (ตามคำตอบอื่น ๆ ) แต่เพื่อเป็นการพิสูจน์แนวคิดนี่เป็นวิธีหนึ่งที่จะทำให้ได้รูปลักษณ์ที่ดีสำหรับการเสริม**kwargsหากคุณใช้ Sphinx อยู่แล้ว


26

Google Style docstrings แยกวิเคราะห์โดย Sphinx

ข้อจำกัดความรับผิดชอบ: ไม่ผ่านการทดสอบ

จาก cutout ของนี้ตัวอย่างเช่นสฟิงซ์ docstringที่*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

มีตัวอย่างหลักของสฟิงซ์ในเอกสารของพวกเขา โดยเฉพาะอย่างยิ่งพวกเขาแสดงสิ่งต่อไปนี้:

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 หลาม ตัวอย่าง docstring ของพวกเขาดูเหมือนจะบอกเป็นนัยว่าพวกเขาไม่ได้เรียก 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 มีคำถามเกี่ยวกับคำตอบที่ยอมรับในการอ้างถึงเอกสารการจัดการกระบวนการย่อย หากคุณนำเข้าโมดูลคุณสามารถดู docstrings ของโมดูลได้อย่างรวดเร็วผ่านการตรวจสอบ getsource

ตัวอย่างจากล่าม python โดยใช้คำแนะนำของ Silent Ghost:

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

แน่นอนว่าคุณยังสามารถดูเอกสารประกอบโมดูลผ่านฟังก์ชั่นวิธีใช้ ตัวอย่างความช่วยเหลือ (กระบวนการย่อย)

ฉันไม่ได้เป็นแฟนตัวเองของ docstring กระบวนการย่อยสำหรับ 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
การแก้ไข: นั่นไม่ใช่ส่วนหนึ่งของเอกสารของสฟิงซ์ แต่เป็น 'ตัวอย่างโครงการ pypi' ที่เป็นอิสระซึ่งอธิบายตัวเองอย่างชัดเจนว่าเป็นการสอนที่ไม่ได้รับอนุญาต
boycy

other_silly_variableไม่ใช่อาร์กิวเมนต์ kwargs แต่เป็นเรื่องปกติอย่างสมบูรณ์
bugmenot123

5

หากใครที่กำลังมองหา Syntax ที่ใช้ได้ .. นี่คือตัวอย่าง docstring นี่เป็นเพียงวิธีที่ฉันทำฉันหวังว่ามันจะเป็นประโยชน์สำหรับคุณ แต่ฉันอ้างไม่ได้ว่ามันสอดคล้องกับสิ่งใดเป็นพิเศษ

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
แล้วอาร์กิวเมนต์คำหลักแต่ละคำล่ะ?
maasha

4

นี้ขึ้นอยู่กับรูปแบบของเอกสารที่คุณใช้ แต่ถ้าคุณกำลังใช้numpydocสไตล์มันจะแนะนำให้ทำเอกสารโดยใช้**kwargsOther Parameters

ตัวอย่างเช่นต่อไปนี้ตัวอย่างของ 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}``.
    """

โดยเฉพาะอย่างยิ่งขอแนะนำให้กำหนดค่าเริ่มต้นของ kwargs เนื่องจากสิ่งเหล่านี้ไม่ชัดเจนจากลายเซ็นฟังก์ชัน


1
ฉันไม่แน่ใจว่าคำแนะนำของคุณมาจากเอกสารรุ่นเก่าหรือประสบการณ์ส่วนตัว แต่เอกสาร "พารามิเตอร์อื่น ๆ " ปัจจุบัน (ที่คุณเชื่อมโยงไปถึง) ระบุว่าควร "ใช้เพื่ออธิบายพารามิเตอร์ที่ใช้ไม่บ่อย" และใช้ "เท่านั้น หากฟังก์ชันมีพารามิเตอร์คีย์เวิร์ดจำนวนมากเพื่อป้องกันไม่ให้ส่วนพารามิเตอร์ไม่เป็นระเบียบ "
Ninjakannon

1

หากคุณกำลังมองหาวิธีทำในรูปแบบnumpydocคุณสามารถพูดถึง**kwargsในส่วนพารามิเตอร์โดยไม่ต้องระบุประเภท - ดังที่แสดงในตัวอย่าง numpydocจากคู่มือนโปเลียนและdocstringส่วนขยายของสฟิงซ์จากเอกสาร pandas sprint 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 ก็แนะนำเช่นเดียวกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.