def decorated(f):
@functools.wraps(f)
def wrapper():
return f()
return wrapper
@decorated
def g():
pass
functools.wraps
does its job at preserving the name of g
:
>>> g.__name__
'g'
But if I pass an argument to g
, I get a TypeError
containing the name of the wrapper:
>>> g(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: wrapper() takes no arguments (1 given)
Where does this name come from? Where is it preserved? And is there a way to make the exception look like g() takes no arguments
?
wraps() is a decorator that is applied to the wrapper function of a decorator. It updates the wrapper function to look like wrapped function by copying attributes such as __name__, __doc__ (the docstring), etc. Parameters: wrapped: The function name that is to be decorated by wrapper function.
Functools module is for higher-order functions that work on other functions. It provides functions for working with other functions and callable objects to use or extend them without completely rewriting them. This module has two classes – partial and partialmethod.
functools. wraps is convenience function for invoking update_wrapper() as a function decorator, when defining a wrapper function. It is equivalent to partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated). So @wraps decorator actually gives a call to functools. partial(func[,*args][, **keywords]).
We simply use the @ symbol before the function we'd like to decorate. Let's show that in practice below.
Martijn's answer covers your first two questions, but there's a better solution: don't make any assumptions about f
's arguments, instead forward all arguments from wrapper()
to f()
:
import functools
def decorated(f):
@functools.wraps(f)
def wrapper(*args, **kwargs): # <- Take any arguments
return f(*args, **kwargs) # <- Forward
return wrapper
@decorated
def g():
pass
g(1)
Output:
Traceback (most recent call last):
File "/home/wja/testdir/tmp.py", line 15, in <module>
g(1)
File "/home/wja/testdir/tmp.py", line 8, in wrapper
return f(*args, **kwargs)
TypeError: g() takes 0 positional arguments but 1 was given
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With