Understanding Python Decorators: Concepts, Examples, and Practical Uses
This article explains Python decorators, covering their definition as higher‑order functions, essential concepts like closures, step‑by‑step examples of basic, parameterized, class‑based, and stateful decorators, as well as practical uses such as logging and caching, all illustrated with clear code snippets.
Python decorators are a powerful and flexible feature that allow you to modify or extend the behavior of functions or methods. A decorator is essentially a higher‑order function that takes a function as an argument and returns a new function, and they are commonly used for logging, performance testing, transaction handling, caching, and permission checks.
Basic concepts
Higher‑order function: a function that accepts one or more functions as input or returns a function. Closure: a function object that remembers the values of the free variables that were in scope when it was defined.
Basic decorator example
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()The @ syntax is syntactic sugar; @my_decorator is equivalent to say_hello = my_decorator(say_hello) . When say_hello() is called, the wrapper function runs.
Decorator with parameters
def repeat(num_times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
greet("Alice")Preserving metadata
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print("Something is happening before the function is called.")
result = func(*args, **kwargs)
print("Something is happening after the function is called.")
return result
return wrapper
@my_decorator
def say_hello():
"""Say hello to the user."""
print("Hello!")
print(say_hello.__name__) # say_hello
print(say_hello.__doc__) # Say hello to the user.Class decorator
def add_class_method(cls):
def decorator(func):
setattr(cls, func.__name__, func)
return cls
return decorator
@add_class_method
class MyClass:
pass
def say_hello(self):
print("Hello from MyClass!")
instance = MyClass()
instance.say_hello() # Hello from MyClass!Decorator composition
def decorator1(func):
def wrapper():
print("Decorator 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("Decorator 2")
func()
return wrapper
@decorator1
@decorator2
def say_hello():
print("Hello!")
say_hello()
# Output:
# Decorator 1
# Decorator 2
# Hello!Stateful decorator (using a class)
class Counter:
def __init__(self, func):
self.func = func
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"Function {self.func.__name__} has been called {self.count} times")
return self.func(*args, **kwargs)
@Counter
def say_hello():
print("Hello!")
say_hello() # Function say_hello has been called 1 times
say_hello() # Function say_hello has been called 2 timesPractical applications
Logging decorator:
import logging
def log_function_call(func):
def wrapper(*args, **kwargs):
logging.info(f"Calling {func.__name__} with args={args} kwargs={kwargs}")
result = func(*args, **kwargs)
logging.info(f"{func.__name__} returned {result}")
return result
return wrapper
@log_function_call
def add(a, b):
return a + b
add(3, 5)Caching with functools.lru_cache :
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(10)) # 55Conclusion
Decorators are a versatile tool in Python that enable you to enhance or modify functions and classes. By mastering decorators, you can write cleaner, more modular, and maintainable code.
Test Development Learning Exchange
Test Development Learning Exchange
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.