📌 Introduction
In Python, decorators are powerful tools that let you add extra functionality to functions, methods, or classes without changing their original code. Think of them as wrappers. they “wrap” around an existing function and run extra code before or after the original function.
They’re widely used in real-world applications, especially in frameworks like Flask and Django, for tasks like logging, authentication, performance measurement, and access control.
⚙️ How Decorators Work
Python treats functions as first-class objects, meaning you can store them in variables, pass them as arguments, and return them from other functions. This flexibility allows decorators to work their magic.
A decorator:
- Takes a function (or class) as input.
- Creates a wrapper function that adds new behavior.
- Returns that wrapper instead of the original function.
Example:
def my_decorator(func):
def wrapper():
print("Before the function runs")
func()
print("After the function runs")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
Output:
Before the function runs
Hello!
After the function runs
Here, my_decorator is shorthand for:
say_hello = my_decorator(say_hello)
🧠 First-Class Functions & Higher-Order Functions
- First-class functions: Functions can be stored in variables, passed as arguments, or returned from other functions.
- Higher-order functions: Functions that take other functions as arguments or return them.
Example:
def apply(func, value):
return func(value)
def square(x):
return x * x
print(apply(square, 5)) # Output: 25
Decorators are higher-order functions because they take a function, modify it, and return a new one.
📚 Real-World Uses of Decorators
- Logging: Record details each time a function runs.
- Authentication: Check if a user is logged in.
- Performance measurement: Track execution time.
- Access control: Restrict certain functions.
- Caching: Store results to avoid recomputation.
Example: Measuring Execution Time:
import time
def timing_decorator(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"Execution time: {end - start} seconds")
return result
return wrapper
@timing_decorator
def slow_function():
time.sleep(2)
print("Done!")
slow_function()
Join the conversation! Your thoughts help the community grow.