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
是参数名称的列表。varargs
和varkw
是名称*
和**
参数或None
。默认值是一个 n 元组 最后 n 个参数的默认值,如果没有,则为 None 默认参数。kwonlyargs
是关键字参数列表 名字。kwonlydefaults
是将名称从kwonlyargs
映射到 默认值。annotations
是一个字典,将参数名称映射到 注释。
所以检查模块有一个叫做kwonlyargs
和kwonlydefaults
的东西。这在实际的函数签名中意味着什么?如果您有一个接受**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 检查模块:仅关键字参数的主要内容,如果未能解决你的问题,请参考以下文章
理解python3函数中的“*”“仅限关键字”参数表示法[重复]