Open In App

Decorators in Python

Last Updated : 19 Jun, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Decorators are a very powerful and useful tool in Python since it allows programmers to modify the behaviour of a function or class. Decorators allow us to wrap another function in order to extend the behaviour of the wrapped function, without permanently modifying it. But before diving deep into decorators let us understand some concepts that will come in handy in learning the decorators.

First Class Objects
In Python, functions are first class objects which means that functions in Python can be used or passed as arguments.
Properties of first class functions:

  • A function is an instance of the Object type.
  • You can store the function in a variable.
  • You can pass the function as a parameter to another function.
  • You can return the function from a function.
  • You can store them in data structures such as hash tables, lists, …

Consider the below examples for better understanding.

Example 1: Treating the functions as objects. 

Python3
# Python program to illustrate functions 
# can be treated as objects 
def shout(text): 
    return text.upper() 

print(shout('Hello')) 

yell = shout 

print(yell('Hello')) 

Output:

HELLO
HELLO

In the above example, we have assigned the function shout to a variable. This will not call the function instead it takes the function object referenced by a shout and creates a second name pointing to it, yell.

Example 2: Passing the function as an argument 

Python3
# Python program to illustrate functions 
# can be passed as arguments to other functions 
def shout(text): 
    return text.upper() 

def whisper(text): 
    return text.lower() 

def greet(func): 
    # storing the function in a variable 
    greeting = func("""Hi, I am created by a function passed as an argument.""") 
    print (greeting) 

greet(shout) 
greet(whisper) 

Output:

HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT.
hi, i am created by a function passed as an argument.

In the above example, the greet function takes another function as a parameter (shout and whisper in this case). The function passed as an argument is then called inside the function greet.

Example 3: Returning functions from another function.

Python3
# Python program to illustrate functions 
# Functions can return another function 

def create_adder(x): 
    def adder(y): 
        return x+y 

    return adder 

add_15 = create_adder(15) 

print(add_15(10)) 

Output:

25


In the above example, we have created a function inside of another function and then have returned the function created inside.
The above three examples depict the important concepts that are needed to understand decorators. After going through them let us now dive deep into decorators.

Decorators

As stated above the decorators are used to modify the behaviour of function or class. In Decorators, functions are taken as the argument into another function and then called inside the wrapper function.

Syntax for Decorator: 

@gfg_decorator
def hello_decorator():
print("Gfg")

'''Above code is equivalent to -

def hello_decorator():
print("Gfg")

hello_decorator = gfg_decorator(hello_decorator)'''

In the above code, gfg_decorator is a callable function, that will add some code on the top of some another callable function, hello_decorator function and return the wrapper function.

Decorator can modify the behaviour:  

Python3
# defining a decorator
def hello_decorator(func):

    # inner1 is a Wrapper function in 
    # which the argument is called
    
    # inner function can access the outer local
    # functions like in this case "func"
    def inner1():
        print("Hello, this is before function execution")

        # calling the actual function now
        # inside the wrapper function.
        func()

        print("This is after function execution")
        
    return inner1


# defining a function, to be called inside wrapper
def function_to_be_used():
    print("This is inside the function !!")


# passing 'function_to_be_used' inside the
# decorator to control its behaviour
function_to_be_used = hello_decorator(function_to_be_used)


# calling the function
function_to_be_used()

Output: 

Hello, this is before function execution
This is inside the function !!
This is after function execution

Let’s see the behaviour of the above code and how it runs step by step when the “function_to_be_used” is called.

Let’s jump to another example where we can easily find out the execution time of a function using a decorator.

Python3
# importing libraries
import time
import math

# decorator to calculate duration
# taken by any function.
def calculate_time(func):
    
    # added arguments inside the inner1,
    # if function takes any arguments,
    # can be added like this.
    def inner1(*args, **kwargs):

        # storing time before function execution
        begin = time.time()
        
        func(*args, **kwargs)

        # storing time after function execution
        end = time.time()
        print("Total time taken in : ", func.__name__, end - begin)

    return inner1



# this can be added to any function present,
# in this case to calculate a factorial
@calculate_time
def factorial(num):

    # sleep 2 seconds because it takes very less time
    # so that you can see the actual difference
    time.sleep(2)
    print(math.factorial(num))

# calling the function.
factorial(10)

Output: 

3628800
Total time taken in : factorial 2.0061802864074707

What if a function returns something or an argument is passed to the function?


In all the above examples the functions didn’t return anything so there wasn’t an issue, but one may need the returned value.

Python3
def hello_decorator(func):
    def inner1(*args, **kwargs):
        
        print("before Execution")
        
        # getting the returned value
        returned_value = func(*args, **kwargs)
        print("after Execution")
        
        # returning the value to the original frame
        return returned_value
        
    return inner1


# adding decorator to the function
@hello_decorator
def sum_two_numbers(a, b):
    print("Inside the function")
    return a + b

a, b = 1, 2

# getting the value through return of the function
print("Sum =", sum_two_numbers(a, b))

Output: 

before Execution
Inside the function
after Execution
Sum = 3

In the above example, you may notice a keen difference in the parameters of the inner function. The inner function takes the argument as *args and **kwargs which means that a tuple of positional arguments or a dictionary of keyword arguments can be passed of any length. This makes it a general decorator that can decorate a function having any number of arguments.

Chaining Decorators

In simpler terms chaining decorators means decorating a function with multiple decorators.

Example: 

Python3
# code for testing decorator chaining 
def decor1(func): 
    def inner(): 
        x = func() 
        return x * x 
    return inner 

def decor(func): 
    def inner(): 
        x = func() 
        return 2 * x 
    return inner 

@decor1
@decor
def num(): 
    return 10

@decor
@decor1
def num2():
    return 10
  
print(num()) 
print(num2())

Output:

400
200

The above example is similar to calling the function as –

decor1(decor(num))
decor(decor1(num2))

Decorators in Python – FAQs

When should you use decorators in Python?

Decorators are used to modify the behavior of functions or methods. Use them when you want to add functionality like logging, caching, or authentication to existing functions without modifying their source code. They help in separating concerns and improving code readability.

What is function vs decorators in Python?

Function: A function in Python is a block of code that performs a specific task, accepts inputs (arguments), processes them, and optionally returns an output.

Decorator: A decorator is a higher-order function that takes another function as an argument, adds some functionality, and returns a new function. It allows modifying or extending behavior of functions or methods.

What is __init__ in Python?

__init__ is a special method (constructor) in Python classes. It’s automatically called when a new instance of a class is created. It initializes the object’s attributes or performs any setup needed for the object.

class MyClass:
def __init__(self, arg1, arg2):
self.arg1 = arg1
self.arg2 = arg2

What is the difference between decorator and annotation in Python?

In Python, a decorator is a function that modifies another function or method.

Annotations are a way to attach metadata to function arguments and return values using the : and -> syntax. They don’t change the function behavior.

# Decorator example
def my_decorator(func):
def wrapper():
print("Something before the function.")
func()
print("Something after the function.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# Annotation example
def greet(name: str) -> str:
return f"Hello, {name}

What is the difference between wrapper and decorator in Python?

  • A wrapper is the inner function defined within a decorator that actually performs the added functionality.
  • A decorator is the outer function that takes a function as an argument, defines a wrapper function to modify it, and returns the wrapper.


Previous Article
Next Article

Similar Reads

Top 10 Python Built-In Decorators That Optimize Python Code Significantly
Python is a widely used high-level, general-purpose programming language. The language offers many benefits to developers, making it a popular choice for a wide range of applications including web development, backend development, machine learning applications, and all cutting-edge software technology, and is preferred for both beginners as well as
12 min read
Decorators with parameters in Python
Prerequisite: Decorators in Python, Function Decorators We know Decorators are a very powerful and useful tool in Python since it allows programmers to modify the behavior of function or class. In this article, we will learn about the Decorators with Parameters with help of multiple examples. Python functions are First Class citizens which means th
4 min read
Memoization using decorators in Python
Recursion is a programming technique where a function calls itself repeatedly till a termination condition is met. Some of the examples where recursion is used are calculation of fibonacci series, factorial, etc. But the issue with them is that in the recursion tree, there can be chances that the sub-problem that is already solved is being solved a
3 min read
Useful cases to illustrate Decorators in python
A decorator is a special kind of function that either takes a function and returns a function or takes a class and returns a class. Well, it can be any callable (i.e functions, classes, methods as they can be called) and it can return anything, it can also take a method. This is also called metaprogramming, as a part of the program tries to modify
4 min read
Nested Decorators in Python
Everything in Python is an object. Even function is a type of object in Python. Decorators are a special type of function which return a wrapper function. They are considered very powerful in Python and are used to modify the behaviour of a function temporarily without changing its actual value. Nesting means placing or storing inside the other. Th
2 min read
Chain Multiple Decorators in Python
In this article, we will try to understand the basic concept behind how to make function decorators and chain them together we will also try to see Python decorator examples. What is Decorator In Python?A decorator is a function that can take a function as an argument and extend its functionality and return a modified function with extended functio
2 min read
Python Decorators: A Complete Guide
A decorator is a design pattern tool in Python for wrapping code around functions or classes (defined blocks). This design pattern allows a programmer to add new functionality to existing functions or classes without modifying the existing structure. The section provides an overview of what decorators are, how to decorate functions and classes, and
9 min read
Conditional Decorators in Python
In Python, decorators are functions or classes that wrap around a function as a wrapper by taking a function as input and returning out a callable. They allow the creation of reusable building code blocks that can either change or extend behavior of other functions. Conditional Decorators Given a condition, the idea here is to execute code or basic
2 min read
Debugging decorators in Python
Decorators in Python are really a very powerful feature. If you are a web developer and you have used the Django framework or even some other development frameworks you would have already come across decorators. For an overview decorators are wrapper functions that wrap an existing function or a method and modify its features. Let's take a short ex
3 min read
Error Handling in Python using Decorators
Decorators in Python is one of the most useful concepts supported by Python. It takes functions as arguments and also has a nested function. They extend the functionality of the nested function. Example: C/C++ Code # defining decorator function def decorator_example(func): print("Decorator called") # defining inner decorator function def
2 min read
Article Tags :
Practice Tags :
three90RightbarBannerImg