用装饰器包装的函数的关键字参数不起作用

时间:2019-03-15 02:27:05

标签: python

我在装饰器上找到的所有教程都建议在包装函数的签名中使用*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有什么意义?我觉得我想念什么。

1 个答案:

答案 0 :(得分:1)

您不想拆开对print的呼叫; print仅接受有限数量的关键字参数,并将拒绝所有其他参数。大概您只是想查看通过了什么,因此无需打开包装即可打印原始tupledict

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都不接受arg2print的关键字,因此它对您大叫。通过拆开包装,print等效于:

    print('during', (), {'arg1': 99, 'arg2': 100})

这是完全有效的(它直接打印tupledict,而不是尝试解压缩)。