If I once used a decorator to my function, how could I run this function alone, without being embedded in a decorator functionality?
For example I have a function printArg
and it prints an argument. For some usability I needed to "mix it" with datetime.now()
. For that I wrote a decorator timeCalled
. Now every time I call printArg
also a decorator called.
Is there a way to call printArg
alone, so I wouldn't repeat myself and wrote another "printArg
" without decorator functionality(datetime.now()
)?
from datetime import datetime
def timeCalled(func):
def wrapper(*args, **kwargs):
print(f'{datetime.now()}: Function called {func.__name__}')
result = func(*args, **kwargs)
return result
return wrapper
@timeCalled
def printArg(arg):
print(f'Your arg is {arg}')
printArg('Mama')
There is no general way that doesn't rely on implementation details. In this particular case, since func
references the original function in wrapper
and is in the closure, you can use:
printArg.__closure__[0].cell_contents
To retrieve it.
More generally, it is good practice to use functools.wraps
when you create the wrapper, this makes the wrapper function "look like" the original function. Moreover, it adds the original function to a __wrapped__
attribute, so:
from datetime import datetime
from functools import wraps
def timeCalled(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f'{datetime.now()}: Function called {func.__name__}')
result = func(*args, **kwargs)
return result
return wrapper
@timeCalled
def printArg(name):
print(f'Your arg is {name=}.')
In which case, you can use:
printArg.__wrapped__