我在下面运行一个装饰演示。
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}
答案 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