Cách chính xác để ghi lại thông số ** kwargs là gì?


99

Tôi đang sử dụng sphinx và plugin autodoc để tạo tài liệu API cho các mô-đun Python của mình. Trong khi tôi có thể thấy cách ghi lại các thông số cụ thể một cách độc đáo, tôi không thể tìm thấy một ví dụ nào về cách ghi lại một **kwargstham số.

Có ai có một ví dụ tốt về một cách rõ ràng để ghi lại những điều này?


Điều này hoàn toàn phụ thuộc vào phương pháp docstring bạn sử dụng. (reStructuredText, Sphinx, Google)
Stevoisiak

2
Điều này không nên được đóng lại. Đó là một câu hỏi hợp lệ. Nó cụ thể (cách ghi lại ** kwargs bằng cách sử dụng nhân sư) Vì các nhận xét của tài liệu không được chuẩn hóa hoàn toàn trong python nên điều này sẽ dẫn đến các ý kiến ​​(hoặc nhiều phương pháp) miễn là chúng hỗ trợ câu hỏi cụ thể (nhân sư).
JerodG

Câu trả lời:


5

Tôi nghĩ subprocesstài liệu của -module là một ví dụ điển hình. Cung cấp một danh sách đầy đủ tất cả các tham số cho một lớp cha / mẹ . Sau đó, chỉ cần tham khảo danh sách đó cho tất cả các lần xuất hiện khác của **kwargs.


97
Tôi có phải là người duy nhất mà câu trả lời này không có ý nghĩa? Tôi không thể tìm thấy ví dụ cụ thể được đề cập.
Acumenus

2
Ví dụ có thể subprocess.call(*popenargs, **kwargs). Nó được ghi lại là subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)nơi mọi thứ sau *phím được nhận dạng trong **kwargs(Hoặc ít nhất là những khóa thường xuyên được sử dụng)
nos

2
Sự tiếp tục có ý nghĩa nhất của điều đó bây giờ subprocess.Popenvà tôi không chắc rằng đó là một ví dụ đặc biệt tuyệt vời nữa.
Donal Fellows

Trừ khi tôi nhầm, nó không còn được ghi lại bằng Python 3.7 nữa.
Mateen Ulhaq

10
Phản đối vì không đưa ví dụ thực tế vào câu trả lời.
naught101

51

Sau khi tìm thấy câu hỏi này, tôi đã giải quyết vấn đề sau, đó là tượng Nhân sư hợp lệ và hoạt động khá tốt:

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

    """

Các r"""..."""yêu cầu để thực hiện điều này "thô" docstring và do đó giữ \*nguyên vẹn (ví Sphinx nhặt như một chữ *và không phải là sự khởi đầu của "chú trọng").

Định dạng đã chọn (danh sách được đánh dấu đầu dòng với loại dấu ngoặc đơn và mô tả được phân tách bằng m-gạch ngang) chỉ đơn giản là để khớp với định dạng tự động do Sphinx cung cấp.

Khi bạn đã thực hiện nỗ lực này để làm cho phần "Đối số từ khóa" trông giống như phần "Tham số" mặc định, có vẻ như việc cuộn phần thông số của riêng bạn ngay từ đầu sẽ dễ dàng hơn (theo một số câu trả lời khác) , nhưng như một bằng chứng về khái niệm, đây là một cách để đạt được giao diện đẹp cho phần bổ sung **kwargsnếu bạn đã sử dụng Sphinx.


26

Chuỗi tài liệu của Google Style được Sphinx phân tích cú pháp

Tuyên bố từ chối trách nhiệm: không được kiểm tra.

Từ cutout này của ví dụ sphinx docstring thì *args**kwargscòn lại chưa giãn nở :

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.

Tôi sẽ đề xuất giải pháp sau cho sự gọn nhẹ:

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

Chú ý cách làm, Optionalkhông bắt buộc đối với các **keyđối số.

Nếu không , bạn có thể cố gắng liệt kê rõ ràng các * args trong Other Parameters**kwargsdưới Keyword Args(xem các phần được phân tích cú pháp ):

    """
    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ó một ví dụ về chuỗi học thuyết cho Sphinx trong tài liệu của họ. Cụ thể chúng hiển thị như sau:

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

Mặc dù bạn đã hỏi về rõ ràng, tôi cũng sẽ chỉ đến Hướng dẫn kiểu Python của Google . Ví dụ về chuỗi docstring của họ dường như ngụ ý rằng họ không gọi tên kwargs một cách cụ thể. (other_silly_variable = Không có)

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 có câu hỏi về câu trả lời được chấp nhận khi tham khảo tài liệu quản lý quy trình con. Nếu bạn nhập một mô-đun, bạn có thể nhanh chóng xem docstrings của mô-đun đó qua opens.getsource.

Một ví dụ từ trình thông dịch python sử dụng đề xuất của Silent Ghost:

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

Tất nhiên bạn cũng có thể xem tài liệu mô-đun thông qua chức năng trợ giúp. Ví dụ trợ giúp (quy trình con)

Cá nhân tôi không phải là một fan hâm mộ của quy trình phụ docstring cho kwargs như một ví dụ, nhưng giống như ví dụ của Google, nó không liệt kê các kwargs một cách riêng biệt như được hiển thị trong ví dụ tài liệu 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()

Tôi bao gồm câu trả lời này cho câu hỏi của ABB vì điều đáng chú ý là bạn có thể xem lại nguồn hoặc tài liệu của bất kỳ mô-đun nào theo cách này để có thông tin chi tiết và nguồn cảm hứng để nhận xét mã của bạn.


2
Đính chính: đó không phải là một phần trong tài liệu của Sphinx, mà là một 'dự án pypi mẫu' độc lập, tự mô tả rõ ràng là một hướng dẫn không có thẩm quyền.
boycy 14/03/18

other_silly_variablekhông phải là một lập luận kwargs, mà là một lập luận hoàn toàn bình thường.
bugmenot123,

4

Nếu bất kỳ ai khác đang tìm kiếm một số cú pháp hợp lệ .. Đây là một docstring ví dụ. Đây chỉ là cách tôi đã làm, tôi hy vọng nó hữu ích cho bạn, nhưng tôi không thể khẳng định rằng nó tuân thủ bất cứ điều gì cụ thể.

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
Vậy còn các đối số từ khóa riêng lẻ thì sao?
maasha

4

Điều này phụ thuộc vào kiểu tài liệu bạn sử dụng, nhưng nếu bạn đang sử dụng kiểu numpydoc thì bạn nên **kwargssử dụng kiểu tài liệu đó Other Parameters.

Ví dụ, sau ví dụ của 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}``.
    """

Đặc biệt lưu ý rằng bạn nên cung cấp các giá trị mặc định của kwargs, vì chúng không rõ ràng từ chữ ký hàm.


1
Tôi không chắc liệu đề xuất của bạn có được rút ra từ các tài liệu cũ hơn hay kinh nghiệm cá nhân hay không, nhưng tài liệu "Các thông số khác" hiện tại (mà bạn liên kết đến) cho biết rằng nó nên được "sử dụng để mô tả các thông số không thường xuyên được sử dụng" và "chỉ được sử dụng nếu một hàm có một số lượng lớn các tham số từ khóa, để tránh làm lộn xộn phần Tham số ".
Ninjakannon

1

Nếu bạn đang tìm cách thực hiện việc này theo kiểu numpydoc , bạn có thể chỉ cần đề cập **kwargstrong phần Tham số mà không chỉ định loại - như được minh họa trong ví dụ về numpydoc từ hướng dẫn napolean và docstring mở rộng nhân sư từ tài liệu gấu trúc sprint 2018.

Dưới đây là một ví dụ mà tôi tìm thấy từ hướng dẫn dành cho nhà phát triển LSST giải thích rất rõ những gì nên là mô tả của **kwargstham số:

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

Ngoài ra, dựa trên những gì @Jonas Adler đề xuất, tôi thấy tốt hơn nên đặt **kwargsvà mô tả của nó trong Other Parametersphần - ngay cả ví dụ này từ hướng dẫn tài liệu matplotlib cũng gợi ý như vậy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.