Sorry for the disturbing title, but I can't put the right words on what I've been looking at for hours now.
I'm using a decorator with optional parameters and i want to alter one of them within the wrapped function so that each call ends up doing a different thing. For context (that I had to remove), i want to create some sort of hash of the original function args and work with that.
from functools import wraps
def deco(s=None):
def _decorate(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(locals())
nonlocal s # Get the deco func arg
if not s:
s = "some_value_depending_on_other_args_i_removed"
# do_smth_smart(s)
# s=None # This solves my issue if uncommented
return None
return wrapper
return _decorate
Here is a small test sample :
@deco()
def test1(self,x):
pass
@deco()
def test2(self,a,b):
pass
test1(1)
test1(2)
test2(3,4)
test2(5,6)
I would expect s to be "reset" to None whenever I call the decorated functions.
To my surprise, as it stands, the output is :
{'args': (1,), 'kwargs': {}, 's': None}
{'args': (2,), 'kwargs': {}, 's': 'newname'}
{'args': (3, 4), 'kwargs': {}, 's': None}
{'args': (5, 6), 'kwargs': {}, 's': 'newname'}
Would someone enlighten me please ? Thanks in advance :)
If we add some
printstatements:We can see that
deco(and_decorate) is only called when decorating thefunctionstest1andtest2:Even here only
wrapperis really called every time along with thefunction it's wrapping, so that's wheresneeds to be; to achieve what you're asking we can do something like assigning_s's__default__value to besinwrapper's parameterdefinition:Outputs: