Примеры использования декораторов в реальных сценариях
Декоратор для логирования
Одним из распространенных применений декораторов является логирование вызовов функций. Это может быть полезно для отладки, мониторинга или аудита.
def log_function_call(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__} with args={args} and kwargs={kwargs}")
return func(*args, **kwargs)
return wrapper
@log_function_call
def add_numbers(a, b):
return a + b
result = add_numbers(2, 3)
print(result)
Это выведет:
Calling add_numbers with args=(2, 3) and kwargs={}
5
Декоратор для кэширования
Декораторы также можно использовать для кэширования результатов ресурсоемких вызовов функций, что улучшает производительность.
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n <= 1:
return n
else:
return (fibonacci(n-1) + fibonacci(n-2))
print(fibonacci(100))
Декоратор lru_cache
из модуля functools
предоставляет простой способ реализации кэша с политикой Least Recently Used (LRU) для результатов функций.
Декоратор для контроля доступа
Декораторы можно использовать для применения контроля доступа к функциям или методам, чтобы гарантировать, что только авторизованные пользователи могут использовать определенную функциональность.
from functools import wraps
def require_admin(func):
@wraps(func)
def wrapper(*args, **kwargs):
if not is_admin(args[0]):
raise ValueError("Access denied. You must be an admin.")
return func(*args, **kwargs)
return wrapper
class User:
def __init__(self, name, is_admin):
self.name = name
self.is_admin = is_admin
@require_admin
def delete_user(self, user_to_delete):
print(f"Deleting user: {user_to_delete.name}")
admin = User("LabEx", True)
regular_user = User("John", False)
admin.delete_user(regular_user) ## Works
regular_user.delete_user(admin) ## Raises ValueError
В этом примере декоратор require_admin
проверяет, является ли пользователь, вызывающий метод delete_user
, администратором, прежде чем разрешить выполнение операции.
Декоратор для повторных попыток
Декораторы также можно использовать для реализации механизма повторных попыток для функций, которые могут завершиться неудачно из-за временных проблем, таких как сетевые ошибки или ограничения по количеству запросов к API.
import time
from functools import wraps
def retry(max_retries=3, delay=1):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
retries = 0
while retries < max_retries:
try:
return func(*args, **kwargs)
except Exception as e:
print(f"Function {func.__name__} failed. Retrying... ({retries+1}/{max_retries})")
retries += 1
time.sleep(delay)
raise Exception(f"Maximum number of retries ({max_retries}) reached for function {func.__name__}")
return wrapper
return decorator
@retry(max_retries=3, delay=2)
def flaky_function():
## Simulate a flaky function that fails 50% of the time
if random.random() < 0.5:
raise Exception("Oops, something went wrong!")
return "Success!"
print(flaky_function())
В этом примере декоратор retry
автоматически повторит вызов функции flaky_function
до 3 раз с задержкой в 2 секунды между каждой попыткой, прежде чем выбросить исключение.
Это лишь несколько примеров из множества реальных сценариев использования декораторов в Python. Декораторы - это мощный и гибкий инструмент, который может помочь вам писать более модульный, поддерживаемый и повторно используемый код.