Mastering Python Decorators: A Deep Dive

 


1. Introduction to Decorators

Python decorators are a powerful way to modify or enhance functions and methods without changing their code. They follow the higher-order function concept, allowing functions to be passed as arguments and returned from other functions.

Basic Example

python
def decorator_function(original_function):
def wrapper_function():
print(f"Executing {original_function.__name__}")
return original_function()
return wrapper_function
@decorator_function
def say_hello():
print("Hello, World!")
say_hello()

🔹 Output:

nginx
Executing say_hello
Hello, World!

💡 @decorator_function is syntactic sugar for say_hello = decorator_function(say_hello).

2. Understanding Function Decorators

Decorators with Arguments

python
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def greet():
print("Hello!")
greet()

🔹 Output:

Hello!
Hello!
Hello!

💡 The decorator takes arguments (n), modifying how the function behaves dynamically.

3. Using functools.wraps to Preserve Metadata

Using functools.wraps ensures that the decorated function retains its original metadata (name, docstring).

python
import functools
def decorator_function(original_function):
@functools.wraps(original_function)
def wrapper_function(*args, **kwargs):
print(f"Executing {original_function.__name__}")
return original_function(*args, **kwargs)
return wrapper_function
@decorator_function
def example():
"""This is an example function."""
print("Example function executed!")
print(example.__name__)  # Retains 'example' instead of 'wrapper_function'
print(example.__doc__) # Displays the function's docstring

4. Chaining Multiple Decorators

You can apply multiple decorators to a function:

python
def uppercase(func):
def wrapper():
return func().upper()
return wrapper
def exclaim(func):
def wrapper():
return func() + "!!!"
return wrapper
@uppercase
@exclaim
def greet():
return "hello"
print(greet())  # Output: HELLO!!!

💡 Execution order: exclaim → uppercase → greet().

5. Class-Based Decorators

Instead of functions, decorators can also be implemented as classes with __call__.

python
class Logger:
def __init__(self, func):
self.func = func
    def __call__(self, *args, **kwargs):
print(f"Logging: {self.func.__name__} called with {args}")
return self.func(*args, **kwargs)
@Logger
def add(a, b):
return a + b
print(add(3, 5))  # Output: Logging: add called with (3, 5)

💡 Useful for stateful decorators that maintain persistent data.

6. Real-World Use Cases

a) Logging Function Calls

python
CopyEdit
import time
def log_time(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.2f}s")
return result
return wrapper
@log_time
def process_data():
time.sleep(2)
print("Data processed!")
process_data()

💡 Use Case: Performance monitoring.

b) Access Control (Authentication Decorator)

python
def requires_auth(role):
def decorator(func):
def wrapper(*args, **kwargs):
user_role = "admin" # Example user role
if user_role != role:
print("Access denied!")
return
return func(*args, **kwargs)
return wrapper
return decorator
@requires_auth("admin")
def sensitive_function():
print("Sensitive operation performed!")
sensitive_function()

💡 Use Case: API authentication.

c) Caching Expensive Function Calls

python
import functools
def cache(func):
cache_data = {}
    @functools.wraps(func)
def wrapper(*args):
if args in cache_data:
print("Fetching from cache...")
return cache_data[args]
result = func(*args)
cache_data[args] = result
return result
return wrapper
@cache
def expensive_calculation(x):
print("Performing expensive calculation...")
return x * x
print(expensive_calculation(4))  # Performs calculation
print(expensive_calculation(4)) # Fetches from cache

💡 Use Case: Optimizing API calls, database queries, or expensive calculations.

Conclusion

Python decorators provide a powerful way to modify functions dynamically while keeping code clean and modular. From simple function wrappers to advanced logging, caching, and authentication, decorators are an essential tool in every Python developer’s toolkit.

WEBSITE: https://www.ficusoft.in/python-training-in-chennai/

Comments

Popular posts from this blog

Best Practices for Secure CI/CD Pipelines

What is DevSecOps? Integrating Security into the DevOps Pipeline

SEO for E-Commerce: How to Rank Your Online Store