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

标签 python

我找到的关于装饰器的所有教程都建议在包装函数的签名中使用 *args, **kwargs 来处理来自包装函数的参数。然而 kwargs 不起作用,而普通参数则:

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 不起作用,那么使用它还有什么意义呢?我感觉我失去了一些东西。

最佳答案

您不想在对 print 的调用中解包; print 仅接受有限数量的关键字参数,并拒绝所有其他参数。想必您只是想查看传递的内容,因此无需解压即可打印原始元组和字典:

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)

arg1arg2 都不是 print 接受的关键字,所以它对你尖叫。通过删除解包,print 等效于:

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

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

关于python - 用装饰器包装的函数的关键字参数不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55174701/

相关文章:

python - 从 Python 3.5 编译 Oracle 包时,不会填充 Oracle 12c DBA_IDENTIFIERS

python - 请帮助证明代码冗余的合理性

python - 如何将字典的字符串值转换为 boolean 值?

python - 我可以在不启动并行进程的情况下在 Django 中运行后台进程吗?

python - Django - 在一个 View 中有两种不同形式并调用函数的问题

python - 如何将递归转换为尾递归

Python 窗口打开和关闭

python - 将 Int64Index 更改为 Index 并将 dtype=int64 更改为 dtype=object

python - 在 python 中使用 lxml 打印 html 实体

python - 使用 zip 对数组的值求和