Python 中的短语“仅关键字 args”有点模棱两可——通常我认为它是指传递给 **kwarg
参数的 args。但是,inspect
模块似乎区分了 **kwarg
和所谓的“仅关键字参数”。
来自 the docs :
inspect.getfullargspec(func)
Get the names and default values of a Python function’s arguments. A named tuple is returned:
FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations)
args
is a list of the argument names.varargs
andvarkw
are the names of the*
and**
arguments orNone
. defaults is an n-tuple of the default values of the last n arguments, or None if there are no default arguments.kwonlyargs
is a list of keyword-only argument names.kwonlydefaults
is a dictionary mapping names fromkwonlyargs
to defaults.annotations
is a dictionary mapping argument names to annotations.
所以 inspect 模块有一些叫做 kwonlyargs
和 kwonlydefaults
的东西。这在实际函数签名中意味着什么?如果你有一个接受 **kwarg
参数的函数签名,在运行时之前你无法真正知道关键字参数的名称,因为调用者基本上可以通过任意字典。那么,kwonlyargs
在函数签名 的上下文中有什么意义 - 这是 inspect.getfullargspec
提供的内容。
最佳答案
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
仅关键字参数允许您在不需要时简单地省略键函数:
max(arg1, arg2, arg3)
而不是做:
max(None, arg1, arg2, arg3)
有关更多信息,您可以查看这些来源:
关于Python 检查模块 : keyword only args,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26963319/