为什么装饰器函数没有检测到默认参数?
Why the decorator function doesn't detect the default parameter?
代码如下:
# 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
值传递给包装装饰器函数?
on_switch
是 keyword-only,您在 之前使用 *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
代码如下:
# 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
值传递给包装装饰器函数?
on_switch
是 keyword-only,您在 之前使用 *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