python装饰器中的“ kwargs”为空

时间:2018-08-31 14:41:58

标签: python decorator

我在下面运行一个装饰演示。

def logger(func):
    def inner(*args, **kwargs):
        print(args)
        print(kwargs)
        return func(*args, **kwargs)
    return inner

@logger
def foo1(a, b, c, x=2, y=1):
    print(x * y)

foo1(6,7,8)

输出为:

(6, 7, 8)
{}
2

为什么字典是空的?我认为应该是{'x':2, 'y':1}

3 个答案:

答案 0 :(得分:2)

问题是参数的默认值在调用时由包装函数对象填充,因为只有包装函数知道它们(它们存储在__kwdefaults__inspect中)。 如果你想让你的装饰者也知道它们,你必须模仿被包装的函数对象会做什么。 对于此任务,您可以使用 from inspect import signature def logger(func): sig = signature(func) def inner(*args, **kwargs): arguments = sig.bind(*args, **kwargs) # these 2 steps are normally handled by func arguments.apply_defaults() print(func, "was called with", arguments) return func(*args, **kwargs) return inner @logger def foo1(a, b, c, x=2, y=1): print(x * y) foo1(6,7,8) 模块:

<function foo1 at 0x7f5811a18048> was called with <BoundArguments (a=6, b=7, c=8, x=2, y=1)>
2

输出:

StringKeysOf<T>

如果您想访问参数,请在 docs 中阅读更多相关信息。

答案 1 :(得分:0)

那是因为函数调用中没有提供kwargs。查看示例:

# kwargs are not provided, function will use default. But decorator know nothing about that.
>>> foo1(6, 7, 8)
(6, 7, 8)
{}
2

# new kwargs are provided and passed to decorator too
>>> foo1(6, 7, 8, x=9, y=10)
(6, 7, 8)
{'x': 9, 'y': 10}
90

答案 2 :(得分:0)

那个字典是空的,因为你没有在 foo1 中传递任何 kwargs。

要获取 x 和 y 而不是空字典,您可以使用

foo1(6,7,8, x=2, y=3) # x and y are printed while printing kwargs

代替

foo1(6,7,8)  # no x and y values are passed so empty dict is print while printing kwargs

请注意,您应该只使用变量 x 和 y。任何其他变量都会导致错误。

正在发生的过程是这样的:

1. foo1 function is tried to called
2. Due to presence of @logger, logger function is called first
3. foo1 function is passed to logger function.
4. inner function takes both type of arguments of foo1 function.
4. *args accepts arguments that are comma separated and should not
   contain key = value type of argument
5. **kwargs accepts arguments that are only key = value type
6. Since you have passed 6,7,8, they are all treated as *args 
7. To pass as **kwargs, you have to pass key = value in foo1 parameters.
8. *args and ** kwargs values are printed
9. foo1 function is called 
10. It executes code inside foo1