我在装饰器上找到的所有教程都建议在包装函数的签名中使用*args, **kwargs
,以处理来自包装函数的参数。但是,kwarg无效,而普通args则有效:
from functools import wraps
def wrapper(a_thing):
@wraps(a_thing)
def do_thing(*args, **kwargs):
print('before')
print(kwargs)
value = a_thing(*args, **kwargs)
print("after", *args, **kwargs)
return value
return do_thing
@wrapper
def output(*args, **kwargs):
print('during', *args, **kwargs)
import pdb; pdb.set_trace()
这是我的交互式输出:
(Pdb) output(99, 100)
before
{}
during 99 100
after 99 100
(Pdb) output(arg1=99, arg2=100)
before
{'arg1': 99, 'arg2': 100}
*** TypeError: 'arg1' is an invalid keyword argument for this function
(Pdb)
以下是其中一种此类教程中的an example:
如果无法使用** kwargs有什么意义?我觉得我想念什么。
答案 0 :(得分:1)
您不想拆开对print
的呼叫; print
仅接受有限数量的关键字参数,并将拒绝所有其他参数。大概您只是想查看通过了什么,因此无需打开包装即可打印原始tuple
和dict
:
def wrapper(a_thing):
@wraps(a_thing)
def do_thing(*args, **kwargs):
print('before')
print(kwargs)
value = a_thing(*args, **kwargs)
print("after", args, kwargs) # Removed unpacking
return value
return do_thing
@wrapper
def output(*args, **kwargs):
print('during', args, kwargs) # Removed unpacking
拆包的要点是,它将经过迭代的*
的元素传递为顺序位置参数,并使用键作为关键字参数将**
的拆包映射中的键值对传递给,值作为关联值。因此,当您这样做时:
print('during', *args, **kwargs)
使用output(arg1=99, arg2=100)
调用了函数,就好像您在运行:
print('during', arg1=99, arg2=100)
arg1
都不接受arg2
和print
的关键字,因此它对您大叫。通过拆开包装,print
等效于:
print('during', (), {'arg1': 99, 'arg2': 100})
这是完全有效的(它直接打印tuple
和dict
,而不是尝试解压缩)。