Hero Vired Logo


Vired Library

Complimentary 4-week Gen AI Course with Select Programs.

Request a callback

or Chat with us on

What Are Decorators in Python? Understanding with Examples

Imagine Python decorators as the magical touch-up artists of your code, the secret sauce that transforms it from a mere script to a masterpiece. These nifty tools don’t just add flair; they seriously amp up the functionality. Imagine having a function that you can tweak without committing to a full-blown rewrite. That’s where decorators shine, allowing you to sprinkle enhancements without diving into a coding saga. They’re like the superheroes of code optimisation, making your scripts more readable, reusable, and easier to maintain. Debugging becomes a breeze and logging? Well, let’s just say decorators turn it into a walk in the code park. So, if you want your Python script to not just run but to dance elegantly through the digital realm, embrace decorators; they’re your code’s best friends, adding that extra touch of brilliance.


Table of Contents:



What are Decorators in Python?


Decorators in Python are a formidable and versatile feature, providing programmers with a potent tool to alter the behaviour of functions or classes. Essentially, decorators enable the encapsulation of one function within another, thereby extending or enhancing the functionality of the wrapped function without making permanent modifications. This ability to augment the behaviour of functions without directly altering their code promotes code reusability and maintainability. Before delving into the intricacies of decorators, it’s essential to grasp certain foundational concepts that pave the way for a more comprehensive understanding of this powerful Python feature. This knowledge serves as a crucial precursor, laying the groundwork for harnessing the full potential of decorators in Python programming.


Types of Python Decorators


Function Decorator


Python Function decorators serve as a valuable tool for extending the functionality of a specific function without directly modifying its code. These decorators operate as higher-order functions, meaning they take a function as input and return a new function that incorporates the desired modifications. By encapsulating the original function within a decorator, developers can dynamically enhance its behaviour without altering the source code. This approach facilitates code reuse, readability, and maintainability, as decorators allow for the addition of new features or modifications to existing functions without the need for extensive changes.


For example:


def simple_decorator(func):


    def wrapper():


    print(“Before function execution”)




print(“After function execution”)


return wrapper




def greet():


    print(“Hello, world!”)




Class Decorator


Class decorators in Python provide a mechanism for enhancing a class’s behaviour without the need to modify its original source code. Much like function decorators, class decorators operate on classes instead of functions. They take a class as input and return a new class with modified or extended functionality. This powerful feature enables developers to dynamically alter class attributes, methods, or properties, fostering code flexibility and maintainability. By employing class decorators, programmers can seamlessly integrate additional functionality into existing classes, promoting a modular and extensible design approach in Python programming.


For example:


def class_decorator(cls):


    class NewClass(cls):


    def new_method(self):


    print(“This is a new method added by the decorator”)


return NewClass




class MyClass:


    def original_method(self):


    print(“This is the original method”)


obj = MyClass()






When to use Python Decorators?


A decorator becomes essential when you wish to alter a function’s behaviour without directly modifying the function. Instances where this proves beneficial include scenarios like incorporating logging, testing performance, implementing caching, validating permissions, and more.


Furthermore, decorators are valuable when the same block of code needs to be executed across multiple functions. This helps in preventing the need for redundant code and promotes a more efficient and maintainable programming approach.


How to Create a Python Decorator?


Creating a Python decorator involves a straightforward step-by-step process. Once you grasp the fundamentals of decorators, the task becomes more accessible. Here’s a concise guide:


  • Define a Higher-Order Function:
    Begin by defining a higher-order function. This function should take another function as its input. In Python, functions are first-class citizens, allowing them to be passed as arguments to other functions.


  • Define a Nested Function (Wrapper):
    Within the higher-order function, create a nested function, often referred to as a wrapper. This inner function will serve as the modification point for the input function. It is within this wrapper that you can extend or modify the behaviour of the original function.


  • Modify or Extend Behavior:
    Inside the wrapper function, call the input function (the one passed as an argument) and perform any additional functionality you desire. This is the stage where you customise the behaviour of the original function. You have the flexibility to add new features or modify the existing ones.


  • Return the Wrapper Function:
    Crucially, ensure that the higher-order function returns the wrapper function. This step is pivotal as it replaces the original function with the wrapper, effectively incorporating the desired modifications.


By following these steps, you can effectively create a Python decorator. This process not only enhances the modularity and reusability of your code but also demonstrates the elegance of Python’s functional programming features. Decorators are powerful tools, and mastering their creation allows for more flexible and maintainable code in Python.


In the following example, we are crafting a basic decorator designed to gauge the execution time of a function.


import time


def timer_decorator(func):


    def wrapper( * args, ** kwargs):


    start_time = time.time()


result = func( * args, ** kwargs)


end_time = time.time()


print(f “{func.__name__} executed in {end_time – start_time:.5f} seconds”)


return result


return wrapper




def slow_function():




print(“Slow function executed”)




Within this illustration, the ‘@’ symbol serves as syntactic sugar, streamlining the application of the decorator to a function. Positioned above a function definition, this symbol signifies that the function is intended to be passed as an argument to the decorator.


Python Decorator Example


Decorators in Python offer a powerful way to modify or extend the behaviour of functions. Here are a few practical examples showcasing the versatility of decorators:


1. Timing Function Execution:


Measuring the execution time of a function is crucial for code optimisation and identifying performance bottlenecks. The following timing decorator accomplishes this without altering the original function’s code:


import time


def timer_decorator(func):

    def wrapper(*args, **kwargs):

        start_time = time.time()

        result = func(*args, **kwargs)

        end_time = time.time()

        print(f”{func.__name__} executed in {end_time – start_time:.5f} seconds”)

        return result

    return wrapper




def slow_function():



print(“Slow function executed”)



2. Authorization and Authentication:


Decorators can enforce access control for functions or methods by verifying user authentication or authorisation. This maintains a clear separation between security concerns and the core functionality of the function:


def is_authenticated(user):

    return user == “authenticated_user”


def authentication_decorator(func):

    def wrapper(*args, **kwargs):

        user = kwargs.get(“user”)

        if is_authenticated(user):

            return func(*args, **kwargs)


            raise PermissionError(“User is not authenticated”)

    return wrapper




def restricted_function(user=None):

    print(“Access granted to the restricted function”)




3. Logging and Error Handling:


Decorators can be employed for consistent logging of function calls or handling errors and exceptions across multiple functions without modifying their individual codes:


import logging


def logging_decorator(func):

    def wrapper(*args, **kwargs):


            logging.info(f”Calling {func.__name__} with arguments {args} and keyword arguments {kwargs}”)

            result = func(*args, **kwargs)

            logging.info(f”Function {func.__name__} executed successfully”)

            return result

        except Exception as e:

            logging.error(f”An error occurred while executing {func.__name__}: {e}”)



    return wrapper




def example_function(a, b):

    return a / b


example_function(10, 5)

example_function(10, 0)


These examples demonstrate the practical use of decorators in Python, showcasing their utility in various scenarios such as performance measurement, access control, and error handling. Decorators contribute to cleaner, more modular, and maintainable code.


Long Story Short:


Python decorators stand as a testament to the language’s flexibility and power, offering a concise and elegant solution for modifying or extending the behaviour of functions. With types ranging from timing decorators for performance optimisation to those handling authentication and error logging, decorators significantly enhance code readability, reusability, and maintainability. As industries increasingly adopt Python for various applications, the demand for proficient decorators and decorators-based solutions is on the rise. To stay ahead in the dynamic field of technology, it becomes imperative to continually enhance one’s skills. If you are eager to delve deeper into Python, consider exploring an Accelerator Program in Artificial Intelligence and Machine Learning at Hero Vired. Equip yourself with cutting-edge knowledge and practical skills, ensuring you are well-positioned to navigate the evolving landscape of technology and make a significant impact in the world of AI and ML. Take the first step toward your transformative journey today!





The @ symbol instructs Python to apply the decorator from the app. route() definition to the function index(). Essentially, a decorator functions as a method that alters the behaviour of another function.
Within Python, a decorator stands out as a distinct type of function, accepting another function as input and yielding a new function as output. These decorators prove instrumental in appending fresh functionality to pre-existing functions or adjusting their behaviour. On a related note, a generator, also a function, functions by providing a sequence of values one at a time. While generators share similarities with iterators, their efficiency surpasses that of iterators, especially when tasked with producing sequences of values that exceed memory storage capacities.
Within the Python programming language, the property() function is an inherent feature designed to generate and yield a property object. The function's syntax is defined as follows: property(fget=None, fset=None, fdel=None, doc=None). In this context, fget represents the function responsible for retrieving the attribute's value, while fset is the function designated for setting the attribute's value.
Decorators empower you to adjust the functionality of functions without making direct changes to their source code, offering a succinct and adaptable approach to augment and broaden their capabilities. This article will delve into the nuances of employing decorators in Python, elucidating their utilisation and presenting instances where their utility proves invaluable.
Employing Python decorators can significantly enhance your coding practices by improving code readability, reusability, and maintainability. These decorators enable you to modify functions without making permanent alterations, offering flexibility in code adjustments. Additionally, they streamline the processes of debugging and logging, making these tasks much more straightforward and efficient.

High-growth programs

Choose the relevant program for yourself and kickstart your career

You may also like

Carefully gathered content to add value to and expand your knowledge horizons

Hero Vired logo
Hero Vired is a premium LearnTech company offering industry-relevant programs in partnership with world-class institutions to create the change-makers of tomorrow. Part of the rich legacy of the Hero Group, we aim to transform the skilling landscape in India by creating programs delivered by leading industry practitioners that help professionals and students enhance their skills and employability.

Data Science

Accelerator Program in Business Analytics & Data Science

Integrated Program in Data Science, AI and ML

Accelerator Program in AI and Machine Learning

Advanced Certification Program in Data Science & Analytics


Certificate Program in Full Stack Development with Specialization for Web and Mobile

Certificate Program in DevOps and Cloud Engineering

Certificate Program in Application Development

Certificate Program in Cybersecurity Essentials & Risk Assessment


Integrated Program in Finance and Financial Technologies

Certificate Program in Financial Analysis, Valuation and Risk Management


Certificate Program in Strategic Management and Business Essentials

Executive Program in Product Management

Certificate Program in Product Management

Certificate Program in Technology-enabled Sales

Future Tech

Certificate Program in Gaming & Esports

Certificate Program in Extended Reality (VR+AR)

Professional Diploma in UX Design

In the News
About Us
Contact us
Vired Library
18003093939     ·     hello@herovired.com     ·    Whatsapp
Privacy policy and Terms of use

© 2024 Hero Vired. All rights reserved