Decorators are powerful and useful tool in Python. It adds functionality to an existing code and modify the behaviour 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.
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. Please see the syntax below:
# defining decorator def decorator_name(funct): def wrapper_function(): statements funct statements return wrapped_function
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.
# use decorator with wrapped function @decorator_name def wrapped_function(): statements
In the below example, 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()
Before Execution. Hello World!. After Execution.
In the below example, 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)
sum of 15 and 10 is 25 . Time taken by MyFunction is 1.000011
In the below example, 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)
Before Execution. Inside wrapped function. After Execution. The sum is 30