Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we need wrapper function in decorators?

If I create a decorator like following:

def my_decorator(some_fun):
    def wrapper():
        print("before some_function() is called.")
        some_fun()
        print("after some_function() is called.")
    return wrapper

@my_decorator
def just_some_function():
    print("Wheee!")

Another decorator can be defined as:

def my_decorator(some_fun):
    print("before some_function() is called.")
    some_fun()
    print("after some_function() is called.")

@my_decorator
def just_some_fun():
    print("some fun")

Both decorators will work the same. What is the benefit of using "wrapper" function inside decorator. I didn't get the purpose.

like image 493
Ankit Mahajan Avatar asked Jul 26 '17 19:07

Ankit Mahajan


People also ask

What is wrapper in decorator?

Decorators allow us to wrap another function in order to extend the behavior of the wrapped function, without permanently modifying it. In Decorators, functions are taken as the argument into another function and then called inside the wrapper function.

What is the role of wrappers?

Wrappers are used for two primary purposes: to convert data to a compatible format or to hide the complexity of the underlying entity using abstraction. Examples include object wrappers, function wrappers, and driver wrappers.

What is the use of wraps in Python?

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.

Why do we use decorators with functions?

Decorators dynamically alter the functionality of a function, method, or class without having to directly use subclasses or change the source code of the function being decorated. Using decorators in Python also ensures that your code is DRY(Don't Repeat Yourself).


1 Answers

The purpose of having a wrapper function is that a function decorator receives a function object to decorate, and it must return the decorated function.

Your 2nd version of my_decorator doesn't have an explicit return statement, so it returns None. When my_decorator is called via the @ decorator syntax

before some_function() is called.
some fun
after some_function() is called.

gets printed, and then None gets assigned to the name just_some_fun. So if you add print(just_some_fun) to the end of that code it will print None.

It may be easier to understand what's going on if we get rid of the @ syntactic sugar and re-write your code using normal function calling syntax:

def my_decorator(some_fun):
    print("before some_function() is called.")
    some_fun()
    print("after some_function() is called.")

def just_some_fun():
    print("some fun")

just_some_fun = my_decorator(just_some_fun)
like image 123
PM 2Ring Avatar answered Sep 21 '22 17:09

PM 2Ring