Decorators in Python

Loading

1. What is a Decorator?

A decorator in Python is a higher-order function that modifies the behavior of another function without changing its code. Decorators allow code reusability, logging, access control, and more.

Key Features of Decorators:
Wraps a function to extend its behavior
Uses @decorator_name syntax
Functions are treated as first-class objects in Python


2. Basic Function Decorator

A decorator is a function that takes another function as input, modifies it, and returns a new function.

2.1 Simple Decorator Example

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

@my_decorator # Applying the decorator
def say_hello():
print("Hello, World!")

say_hello()

Output:

Before function execution
Hello, World!
After function execution

3. Using functools.wraps

When using decorators, function metadata (__name__, __doc__) may be lost. To preserve metadata, use functools.wraps:

import functools

def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print("Before function execution")
result = func(*args, **kwargs)
print("After function execution")
return result
return wrapper

@my_decorator
def greet(name):
"""Greet a person by name."""
print(f"Hello, {name}!")

print(greet.__name__) # Output: greet
print(greet.__doc__) # Output: Greet a person by name.

4. Decorators with Arguments

A decorator can accept arguments by wrapping it inside another function:

import functools

def repeat(n):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return wrapper
return decorator

@repeat(3) # Executes function 3 times
def say_hi():
print("Hi!")

say_hi()

Output:

CopyEditHi!
Hi!
Hi!

5. Decorating Functions with Arguments

If a function has parameters, the decorator must accept *args and **kwargs:

def uppercase_decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result.upper()
return wrapper

@uppercase_decorator
def greet(name):
return f"Hello, {name}"

print(greet("Alice")) # Output: HELLO, ALICE

6. Applying Multiple Decorators

You can stack multiple decorators:

def bold(func):
def wrapper():
return f"<b>{func()}</b>"
return wrapper

def italic(func):
def wrapper():
return f"<i>{func()}</i>"
return wrapper

@bold
@italic
def text():
return "Hello"

print(text()) # Output: <b><i>Hello</i></b>

Order matters: The closest decorator to the function runs first.


7. Class-Based Decorators

You can define decorators using classes with __call__ method:

class LogDecorator:
def __call__(self, func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__} with arguments {args} {kwargs}")
return func(*args, **kwargs)
return wrapper

@LogDecorator()
def add(a, b):
return a + b

print(add(2, 3)) # Output: Calling add with arguments (2, 3) {} -> 5

8. Common Use Cases of Decorators

Use CaseExample
Logging@log_decorator to track function calls
Authentication@auth_required to restrict access
Memoization (Caching)@functools.lru_cache for caching
Timing Execution@time_it to measure execution time
Input Validation@validate_input to check arguments

9. Built-in Python Decorators

Python provides built-in decorators:

DecoratorPurpose
@staticmethodDefines a static method inside a class
@classmethodDefines a class method
@propertyDefines a getter method
@functools.lru_cacheCaches function results

Leave a Reply

Your email address will not be published. Required fields are marked *