Python 检查模块:仅关键字参数

Posted

技术标签:

【中文标题】Python 检查模块:仅关键字参数【英文标题】:Python inspect module: keyword only args 【发布时间】:2015-01-13 19:28:55 【问题描述】:

Python 中的短语“仅关键字 args”有点模棱两可——通常我认为它是指传递给 **kwarg 参数的 args。但是,inspect 模块似乎区分了**kwarg 和所谓的“仅关键字参数”。

来自the docs

inspect.getfullargspec(func)

获取 Python 函数参数的名称和默认值。一种 返回命名元组:

FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations)

args 是参数名称的列表。 varargsvarkw 是名称 *** 参数或 None。默认值是一个 n 元组 最后 n 个参数的默认值,如果没有,则为 None 默认参数。 kwonlyargs 是关键字参数列表 名字。 kwonlydefaults 是将名称从 kwonlyargs 映射到 默认值。 annotations 是一个字典,将参数名称映射到 注释。

所以检查模块有一个叫做kwonlyargskwonlydefaults 的东西。这在实际的函数签名中意味着什么?如果您有一个接受**kwarg 参数的函数签名,那么直到运行时您才能真正知道关键字参数的名称,因为调用者基本上可以传递任意字典。那么,kwonlyargs 函数签名 的上下文中具有什么意义 - 这是 inspect.getfullargspec 提供的。

【问题讨论】:

【参考方案1】:

TL;DR:仅关键字参数与普通关键字参数不同。


仅关键字参数是在函数调用中出现在 *args 之后和 **kwargs 之前的参数。例如,考虑这个通用函数头:

def func(arg, *args, kwonly, **kwargs):

在上面,kwonly 采用仅关键字参数。这意味着你必须在给它一个值时提供它的名字。换句话说,你必须明确地写:

func(..., kwonly=value, ...)

而不仅仅是传递一个值:

func(..., value, ...)

为了更好地解释,请考虑上面给出的函数的这个示例调用:

func(1, 2, kwonly=3, kw=4)

当 Python 解释这个调用时,它将:

arg 分配给1,因为它在函数签名中的位置与调用中1 的位置相匹配。

2 放在*args 中,因为*args 收集任何额外的位置参数,而2 是额外的。

kwonly 分配给3,因为我们已经(必要时)明确告诉它这样做。请注意,如果我们改为这样做:

func(1, 2, 3, kw=4)

3 也将被放置在 *args 中,并且 TypeError 将因未向 kwonly 提供参数而引发(因为在这种情况下我们没有给它一个默认值)。

kw=4放在**kwargs中,因为它是一个额外的关键字参数,由**kwargs收集。

下面是我上面所说的演示:

>>> def func(arg, *args, kwonly, **kwargs):
...     print('arg:', arg)
...     print('args:', args)
...     print('kwonly:', kwonly)
...     print('kwargs:', kwargs)
...
>>> func(1, 2, kwonly=3, kw=4)
arg: 1
args: (2,)
kwonly: 3
kwargs: 'kw': 4
>>>
>>> func(1, 2, 3, kw=4)  # Should have written: 'kwonly=3'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() missing 1 required keyword-only argument: 'kwonly'
>>>

基本上,您可以将仅关键字参数视为关键字参数,在给它们赋值时,您必须提供参数的名称。与普通关键字参数一样,位置值是不够的。

>>> def func(kw=None):
...     print('kw:', kw)
...
>>> func(kw=1)
kw: 1
>>> func(1)  # Do not need the name in this case.
kw: 1
>>>
>>> def func(*, kwonly=None):
...     print('kwonly:', kwonly)
...
>>> func(kwonly=1)
kwonly: 1
>>> func(1)  # Always need the name with keyword-only arguments.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() takes 0 positional arguments but 1 was given
>>>

最后,我知道有些人在想“为什么还要使用仅关键字参数?”答案很简单,在某些情况下它们使事情更具可读性(尤其是对于带有可变数量参数的函数)。

例如,考虑内置的max 函数及其关键字key 参数。什么对您来说更具可读性?做这样的事情:

max(lambda x: -x, arg1, arg2, arg3)

并让人们记住max 的第一个参数始终是key function,或者这样做:

max(arg1, arg2, arg3, key=lambda x: -x)

并向所有人明确lambda x: -x 是您的关键职能。此外,将 key 设为仅关键字参数可以让您在不需要时简单地省略 key 函数:

max(arg1, arg2, arg3)

而不是做:

max(None, arg1, arg2, arg3)

有关更多信息,您可以查看以下来源:

https://docs.python.org/3/reference/compound_stmts.html#function https://docs.python.org/3/reference/expressions.html#calls https://docs.python.org/3/glossary.html#term-parameter

【讨论】:

以上是关于Python 检查模块:仅关键字参数的主要内容,如果未能解决你的问题,请参考以下文章

python 仅关键字参数

理解python3函数中的“*”“仅限关键字”参数表示法[重复]

Python的函数和参数

python--关键字参数/可变参数--内置函数--时间模块--常用模块

Python---函数---命名关键字参数

[转]Python函数的各种参数用法(含星号参数)