Python - Decorators
Decorators are powerful and useful tool in Python. It adds functionality to an existing code and modify the behavior of the code while compiling it. for example - It allows a programmer to wrap a function (a.k.a wrapper function) around a given function (a.k.a wrapped function) in order to modify the behavior of the given function, without permanently modifying it.
Create a Decorator
The decorator is created exactly same as any function in python and takes function as an argument. Inside decorator, a wrapper function is created which is wrapped around the function which is passed as an argument. See the syntax below:
Syntax
# defining decorator def decorator_name(funct): def wrapper_function(): statements funct statements return wrapped_function
Use a Decorator
To use a decorator with a function, a line containing @decorator name must be added above the function definition as shown in syntax below. Along with this, The argument definition of wrapped function must match inside and outside of the decorator.
Syntax
# use decorator with wrapped function @decorator_name def wrapped_function(): statements
Example: function with no argument and not a return type
In the example below, a decorator called MyDecorator is created. Inside it, a wrapper function called MyWrapperFunction is created which prints a message just before and after execution of the wrapped function called MyFunction. The argument definition of wrapped function must match inside and outside of the decorator.
def MyDecorator(funct): def MyWrapperFunction(): print("Before Execution") funct() print("After Execution") return MyWrapperFunction @MyDecorator def MyFunction(): print("Hello World!") MyFunction()
The output of the above code will be:
Before Execution Hello World! After Execution
Example: function with arguments and not a return type
In the example below, wrapped function called MyFunction takes two numbers as arguments and prints the sum of those numbers with a given message. As mentioned above, the argument definition of the wrapped function must match inside and outside the decorator, hence a and b arguments are passed through wrapper function which is again passed through wrapped function inside the decorator. In this example, the wrapper function is defined to calculate the time taken by wrapped function to perform the execution of given task.
import time def MyDecorator(funct): def MyWrapperFunction(a, b): start = time.time() funct(a, b) end = time.time() # 1 is added because the execution time is very small. print("Time taken by", funct.__name__, "is", 1+end-start) return MyWrapperFunction @MyDecorator def MyFunction(a, b): print("sum of", a, "and", b, "is", a+b, ".") MyFunction(15, 10)
The output of the above code will be:
sum of 15 and 10 is 25 . Time taken by MyFunction is 1.0000081062316895
Example: function with arguments and a return type
In the example below, wrapped function called MyFunction returns value. Hence, there must be a return statement inside the wrapper function to get return from wrapped function. Please note that, in this example, *arg, **kwarg parameters are used to match with the argument definition of wrapped function.
def MyDecorator(funct): def MyWrapperFunction(*arg, **kwarg): print("Before Execution.") abc = funct(*arg, **kwarg) print("After Execution.") return abc return MyWrapperFunction @MyDecorator def MyFunction(a, b, c): print("Inside wrapped function.") return a + b + c x = MyFunction(15, 10, 5) print("The sum is", x)
The output of the above code will be:
Before Execution. Inside wrapped function. After Execution. The sum is 30