为什么Decorator函数没有检测到默认参数?

时间:2019-06-25 21:03:51

标签: python-3.x decorator default-value

代码如下:

# Decorators
def on_or_off(func):
    def wrapper(*args, on_switch, **kwargs):
        if on_switch:
            func(*args, on_switch=on_switch, **kwargs)
    return wrapper

@on_or_off
def print_101(on_switch=False):
    print ('101')

print_101()

# TypeError: wrapper() missing 1 required keyword-only argument: 'on_switch'

我认为默认的on_switch值将传递给包装函数,但事实并非如此。 print_101()行如何保持不变,并允许将默认的on_switch值传递给包装装饰器函数?

1 个答案:

答案 0 :(得分:1)

on_switch仅适用于关键字,您可以通过在其之前使用*args 声明它。

print_101现在引用wrapper函数,因为它是必需的,所以缺少on_switch参数。

您可以通过在包装器中声明其默认值来解决此问题:

# Decorators
def on_or_off(func):
    def wrapper(*args, on_switch=False, **kwargs):
        if on_switch:
            func(*args, on_switch=on_switch, **kwargs)
    return wrapper

从理论上讲,您可以查看func.__defaults__或使用inspect模块来自动找出默认值,但这可能是过大的:

# Decorators
def on_or_off(func):
    bindings = dict(zip(func.__code__.co_varnames, func.__defaults__))
    bindings.update(func.__kwdefaults__)
    def wrapper(*args, on_switch=bindings["on_switch"], **kwargs):
        if on_switch:
            func(*args, on_switch=on_switch, **kwargs)
    return wrapper