Here is the code:
# 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'
I thought the default on_switch
value will pass to the wrapper function, but it doesn't. How can the line print_101()
remains the same and allows for passing the default on_switch
value to the wrapper decorator function?
on_switch
is keyword-only, you declared it as such by using *args
before it.
print_101
now refers to the wrapper
function, which is missing the on_switch
argument, because it's required.
You can solve this by declaring its default value inside the wrapper:
# 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
Theoretically, you could look into func.__defaults__
or use the inspect
module to automatically figure out the default value, but that's probably overkill:
# 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