In Python, decorators are a powerful feature used to modify or enhance functions and classes. They are a key part of advanced metaprogramming and are frequently used in logging, authentication, caching, metrics, and tracing in production systems. This document provides an in-depth explanation of the syntax and all common use cases of Python decorators with professional examples aimed at deep learning engineers.
1. Basic Syntax of a Decorator
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Before function call")
result = func(*args, **kwargs)
print("After function call")
return result
return wrapper
@my_decorator
def say_hello(name):
print(f"Hello, {name}!")
say_hello("Alice")
@my_decorator is equivalent to writing say_hello = my_decorator(say_hello)
.
2. Stacking Multiple Decorators
def deco1(func):
def wrapper(*args, **kwargs):
print("deco1")
return func(*args, **kwargs)
return wrapper
def deco2(func):
def wrapper(*args, **kwargs):
print("deco2")
return func(*args, **kwargs)
return wrapper
@deco1
@deco2
def greet():
print("Greetings")
greet()
This applies decorators from the bottom up: greet = deco1(deco2(greet))
.
3. Parameterized Decorators
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def shout():
print("Python!")
shout()
This is called a decorator factory that generates decorators dynamically.
4. Using functools.wraps
from functools import wraps
def log(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
@log
def process():
"""Does something important"""
print("Processing")
print(process.__name__)
print(process.__doc__)
@wraps
preserves the metadata (name, docstring) of the original function.
5. Applying Decorators to Classes
def class_decorator(cls):
cls.extra_attr = 'injected'
return cls
@class_decorator
class MyClass:
pass
print(MyClass.extra_attr)
Since classes are objects, decorators can wrap them too.
6. Decorating Methods Inside a Class
def log_method(func):
@wraps(func)
def wrapper(self, *args, **kwargs):
print(f"Method {func.__name__} called")
return func(self, *args, **kwargs)
return wrapper
class Logger:
@log_method
def run(self):
print("Running")
Logger().run()
7. Using Decorators for Authentication
def require_admin(func):
@wraps(func)
def wrapper(user):
if user != 'admin':
raise PermissionError("Access denied")
return func(user)
return wrapper
@require_admin
def view_dashboard(user):
print("Dashboard visible")
view_dashboard("admin")
8. Advanced Use: Class-Based Decorators
class CountCalls:
def __init__(self, func):
self.func = func
self.calls = 0
def __call__(self, *args, **kwargs):
self.calls += 1
print(f"Call {self.calls} to {self.func.__name__}")
return self.func(*args, **kwargs)
@CountCalls
def hello():
print("Hello")
hello()
hello()
Conclusion
Decorators are a vital tool for advanced Python developers. They increase code modularity, reusability, and readability. The provided examples demonstrate how decorators can be applied in real-world machine learning and deep learning projects, especially for logging, validation, caching, and profiling. functools.wraps
is particularly essential to maintain proper function introspection.
Comments
Post a Comment