# Python Decorators

## Python Decorators

Python decorators modify the behavior of the existing code while compiling it. It allows defining one function inside another or 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. They are powerful and useful in Python and adds functionality to an existing code.

## Create Python Decorators

In Python, to create a decorator, it is defined exactly like any other function and takes a function as a parameter. Inside it, a wrapper function is created which is wrapped around the function that was passed to the decorator as an argument. Syntax of creation of a decorator is given below:

### Python Decorators Syntax:

# creating a decorator
def decorator_name(func):
def wrapper_function():
statements
func
statements
return wrapper_function

## Using Python Decorators

To use a decorator in Python, a line containing @decorator_name must be added above the function definition of the wrapped function. Make sure that the argument definition of the wrapped function matches inside and outside of the decorator. Syntax of using a decorator is provided below:

### Syntax of using a decorator:

# use decorator with wrapped function
@decorator_name
def wrapped_function():
statements

### Example: Function with no argument and no return type

# Python program to exemplify using a decorator

def Decorator(func):
def WrapperFunction():
print("Before Execution")
func()
print("After Execution")
return WrapperFunction

@Decorator
def Function():
print("StudyExperts!")

Function()

In the program provided above, a decorator named “Decorator” is created which takes a function named “Function” as an argument. Inside the decorator, a wrapper function named “WrapperFunction” is defined with three statements, one of which is a call to the function that was passed to the Decorator as an argument. Decorator returns the WrapperFunction. Decorator is then called.

Output:

Before Execution
StudyExperts!
After Execution
StudyExperts!

### Example: Function with arguments and no return type

import time

def Decorator(func):
def WrapperFunction(x, y):
start_time = time.time()
func(x, y)
end_time = time.time()
# 1 is added because the execution time is very small.
print("Time taken by", func.__name__, "is", 1+end_time-start_time)
return WrapperFunction

@Decorator
def Function(x, y):
print("sum of", x, "and", y, "is", x+y, ".")

Function(21, 30)

In the program provided above, a decorator named “Decorator” is created which takes a function named “Function” as an argument. Inside the decorator, a wrapper function named “WrapperFunction” is defined with four statements, one of which is a call to the function that was passed to the Decorator as an argument. Decorator returns the WrapperFunction. Decorator is then called with the function “Function” which takes two parameters.

Output:

sum of 21 and 30 is 51 .
Time taken by Function is 1.0000081062316895

### Example: Function with arguments and a return type

def Decorator(func):
def WrapperFunction(*arg, **kwarg):
print("Before Execution.")
var = func(*arg, **kwarg)
print("After Execution.")
return var
return WrapperFunction

@Decorator
def Function(x, y, z):
print("Inside wrapped function.")
return x + y + z

sum_var = Function(11, 20, 54)
print("The sum is", sum_var)

In the program provided above, a decorator named “Decorator” is created which takes a function named “Function” as an argument. Inside the decorator, a wrapper function named “WrapperFunction” is defined with three statements, one of which is a call to the function that was passed to the Decorator as an argument. Decorator returns the WrapperFunction. Decorator is then called with the function “Function” which takes three parameters and returns the sum of these parameters.

Output:

Before Execution.
Inside wrapped function.
After Execution.
The sum is 85