A decorator is a function that takes in another function as argumen, it adds extra functionality to the function without actually modifying it.
Typically, decorator functions defines another inner function that is called a wrapper, the wrapper function is responsible of calling the decorated function,
Consider the following example:
In the above example, we defined a decorator function called addition_decorator
, it takes in a function to add two numbers as arguments. It then prettifies the outputs of the function by visually showing the evaluation of the addition operation. Note that without decorating add()
, it would simply output the sum of a
and b
.
The purpose of functools.wraps()
When a function is decorated, the wrapper function does not automatically inherit some important properties such as the name, the docstring, annotations, etc from the decorated function. Consider the following example:
The wraps()
decorator function in the functools
module is a decorator that updates the wrapper function so that it becomes indistinguishable from the decorated function. This means that the wrapper function inherits the name of the original function as well as other important attributes such as the docstring.
The syntax of the wraps()
function is as shown below:
def decorator(func):
@functools.wraps(func)
def wrapper_decorator(*args, **kwargs):
# Do something
It takes the original function as the argument, it then applies its attributes to the wrapper. Consider the following example;
As you can see above, the wrapper
function now has attributes that are similar to that of the decorated function. Such attributes includes the ones shown above i.e __doc__
and __name__
as well as others.