What is a Decorator in Python?
A decorator in Python is a function that adds extra functionality to another function without modifying the original function’s source code.
In simple words:
A decorator acts like a wrapper around an existing function.
Decorators help developers write reusable and maintainable code by separating additional features from the core business logic.

Real-Life Example of Decorators
Consider ordering a cup of coffee.
- Coffee = Original function
- Sugar, milk, or cream = Extra functionality added through decorators
The original coffee remains the same, but its functionality or behavior becomes enhanced.
The same concept applies to Python decorators.
Why Do We Need Decorators in Python?
In real-world programming, developers often need to add similar functionality to multiple functions repeatedly.
Some common examples include:
- Logging function execution
- User authentication
- Measuring execution time
- Exception handling
- Access control
- API validation
- Monitoring application performance
Without decorators, the same code would need to be written repeatedly inside multiple functions, making the program harder to maintain.
Decorators solve this problem by allowing reusable functionality to be added externally.
Functions as Objects in Python
Before understanding decorators, it is important to understand that functions are treated as objects in Python.
This means:
- Functions can be assigned to variables
- Functions can be passed as arguments
- Functions can be returned from other functions
Example: Function Assigned to a Variable
def greet():
print("Hello")
say_hello = greet
say_hello()
Output
Hello
In this example, the function greet is assigned to another variable called say_hello.
This demonstrates that functions behave like normal objects in Python.
Functions Inside Functions in Python
Python also allows defining one function inside another function.
This concept is called nested functions or inner functions.
Example: Inner Function
def outer():
def inner():
print("Inside inner function")
inner()
outer()
Output
Inside inner function
Inner functions are an important building block for Python decorators.
Returning Functions in Python
Python functions can also return other functions.
This feature is heavily used while creating decorators.
Example: Returning a Function
def outer():
def inner():
print("Hello from inner")
return inner
func = outer()
func()
Output
Hello from inner
Here:
- outer() returns the inner function
- func stores the returned function
- func() executes the inner function
This concept forms the foundation of decorators.
Basic Idea of Python Decorators
Before creating an actual decorator, let us manually add extra functionality to a function.
Without Using a Decorator
def greet():
print("Hello!")
def add_message():
print("Welcome!")
greet()
add_message()
Output
Welcome!
Hello!
Here, extra functionality was added manually.
However, this approach becomes repetitive when multiple functions require similar behavior.
Decorators solve this issue elegantly.
Creating a Decorator in Python
Now let us convert the previous example into a proper Python decorator.
Example: Basic Decorator
def my_decorator(func):
def wrapper():
print("Welcome!")
func()
return wrapper
@my_decorator
def greet():
print("Hello!")
greet()
Output
Welcome!
Hello!
How Python Decorators Work
The decorator process works step by step as follows:
- my_decorator accepts a function as an argument
- Inside it, a new function called wrapper is created
- The wrapper function adds additional behavior
- The original function is executed inside the wrapper
- The wrapper function is returned
- @my_decorator replaces the original function with the wrapper
Internally, Python performs this operation:
greet = my_decorator(greet)
This is the core mechanism behind decorators in Python.
Decorators with Function Arguments
Most real-world functions accept parameters. Therefore, decorators should also support arguments.
Example: Decorator with Arguments
def my_decorator(func):
def wrapper(name):
print("Welcome!")
func(name)
return wrapper
@my_decorator
def greet(name):
print("Hello", name)
greet("Naveen")
Output
Welcome!
Hello Naveen
This example shows how decorators can work with function parameters.
Using *args and **kwargs in Decorators
In Python, decorators often use *args and **kwargs to support functions with any number of positional and keyword arguments.
This makes decorators flexible and reusable.
Example: Flexible Decorator
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Before function")
func(*args, **kwargs)
print("After function")
return wrapper
@my_decorator
def add(a, b):
print(a + b)
add(5, 3)
Output
Before function
8
After function
Using *args and **kwargs is considered a best practice while creating decorators.
Real-Time Example of Logging Decorator
Logging is one of the most common uses of decorators in Python applications.
Example: Logging Decorator
def log_decorator(func):
def wrapper(*args, **kwargs):
print("Function is starting...")
func(*args, **kwargs)
print("Function finished.")
return wrapper
@log_decorator
def process():
print("Processing data...")
process()
Output
Function is starting...
Processing data...
Function finished.
This decorator automatically logs function execution without modifying the original function.
Real-Time Example of Authentication Decorator
Authentication decorators are commonly used in web applications.
Example: Authentication Decorator
def authenticate(func):
def wrapper():
user = "admin"
if user == "admin":
func()
else:
print("Access Denied")
return wrapper
@authenticate
def dashboard():
print("Welcome to dashboard")
dashboard()
Output
Welcome to dashboard
This example demonstrates how decorators can restrict access based on authentication conditions.
Multiple Decorators in Python
Python allows applying multiple decorators to the same function.
Example: Multiple Decorators
def decorator1(func):
def wrapper():
print("First")
func()
return wrapper
def decorator2(func):
def wrapper():
print("Second")
func()
return wrapper
@decorator1
@decorator2
def say_hello():
print("Hello")
say_hello()
Output
First
Second
Hello
Decorators execute from bottom to top.
In this case:
- decorator2 executes first
- decorator1 wraps the result
Advantages of Python Decorators
Python decorators provide several important benefits.
Code Reusability
The same decorator can be reused across multiple functions.
Cleaner Code
Decorators keep additional functionality separate from the main business logic.
Better Readability
Programs become easier to understand and maintain.
Improved Maintainability
Changes can be made in one decorator instead of modifying multiple functions.
Separation of Concerns
Decorators separate core functionality from secondary features like logging or authentication.

Where Python Decorators Are Used
Decorators are widely used in modern Python applications.
Web Frameworks
Popular frameworks like Flask and Django heavily rely on decorators.
Flask Example
@app.route('/')
def home():
return "Hello World"
Here, @app.route() is a decorator that maps URLs to functions.
Logging Systems
Decorators automatically track application events and errors.
Authentication Systems
Decorators validate user permissions before executing functions.
Performance Monitoring
Execution time measurement can be added using decorators.
Caching
Decorators help improve performance by storing computed results.
Common Mistakes While Using Decorators
Beginners often make a few common mistakes while working with decorators.
Forgetting to Return the Wrapper Function
If the wrapper function is not returned, the decorator will not work correctly.
Incorrect Argument Handling
Failing to use *args and **kwargs can make decorators incompatible with different functions.
Overcomplicating Logic
Simple functionality should not be unnecessarily wrapped in complex decorators.
Best Practices for Python Decorators
To write efficient decorators:
- Use meaningful decorator names
- Prefer *args and **kwargs
- Keep decorators simple and reusable
- Avoid unnecessary nesting
- Add proper documentation
- Use decorators only when reusable functionality is required
Difference Between Decorators and Normal Functions
| Feature | Normal Function | Decorator |
|---|
| Purpose | Performs a task | Extends another function |
| Code Reusability | Limited | High |
| Modifies Existing Functionality | No | Yes |
| Used for Cross-Cutting Concerns | Rarely | Frequently |
Python Decorators in Real-World Applications
Decorators are heavily used in:
- API development
- Machine learning pipelines
- Web frameworks
- Cloud applications
- Automation scripts
- Data processing systems
- Enterprise software development
Because of their flexibility, decorators are considered an advanced but essential Python programming concept.
Conclusion
Python decorators are one of the most powerful and elegant features of the Python programming language. They allow developers to extend the behavior of functions without changing the original source code.
By understanding:
- Functions as objects
- Nested functions
- Returning functions
- Wrapper functions
- *args and **kwargs
Developers can easily master decorators.
Decorators improve code readability, reusability, maintainability, and scalability. They are extensively used in modern software development for authentication, logging, caching, profiling, routing, and monitoring.
Whether you are a beginner learning Python programming or an experienced developer building advanced applications, understanding Python decorators will significantly improve your coding skills and software design practices.
