Intermediate

Decorators in Python

Decorators allow you to modify the behavior of a function without changing its source code. They are widely used in frameworks, logging, authentication, and performance monitoring.

What is a Decorator?

A decorator is a function that takes another function as input and returns a new function with added behavior.

💡 Decorators use the @ symbol and are based on higher-order functions.

Basic Function Without Decorator

def greet():
    print("Hello!")

greet()
        

Creating a Simple Decorator

def my_decorator(func):
    def wrapper():
        print("Before function call")
        func()
        print("After function call")
    return wrapper
        

Applying the decorator:

@my_decorator
def greet():
    print("Hello!")

greet()
        

How Decorators Work

Decorator with Arguments

To handle functions with parameters, the wrapper must accept arguments.

def logger(func):
    def wrapper(*args, **kwargs):
        print("Function called:", func.__name__)
        return func(*args, **kwargs)
    return wrapper
        
@logger
def add(a, b):
    return a + b

print(add(3, 5))
        

Preserving Function Metadata

Decorators can hide function name and docstring. Use functools.wraps to preserve them.

from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper():
        print("Running...")
        func()
    return wrapper
        

Real-World Uses of Decorators

📝 Practice:
Create a decorator that prints the execution time of a function.