Ответ
Да, декораторы в Python могут принимать аргументы. Для этого используется дополнительный уровень вложенности функций. Такой декоратор часто называют "декоратором с параметрами".
Структура декоратора с аргументами:
- Внешняя функция принимает аргументы декоратора.
- Она возвращает функцию-декоратор (обычно называемую
decorator). - Эта функция-декоратор принимает целевую функцию (
func) и возвращает функцию-обёртку (wrapper).
Пример: декоратор для повторного выполнения функции с заданным количеством попыток.
import time
from functools import wraps
def retry(max_attempts=3, delay=1):
"""Декоратор для повторного вызова функции при возникновении исключения."""
def decorator(func):
@wraps(func) # Сохраняем метаданные оригинальной функции
def wrapper(*args, **kwargs):
last_exception = None
for attempt in range(1, max_attempts + 1):
try:
print(f"Попытка {attempt} из {max_attempts}")
return func(*args, **kwargs)
except Exception as e:
last_exception = e
if attempt < max_attempts:
time.sleep(delay)
# Если все попытки исчерпаны
raise last_exception
return wrapper
return decorator
# Использование с аргументами по умолчанию
@retry()
def connect_to_service():
# ... логика подключения
pass
# Использование с кастомными аргументами
@retry(max_attempts=5, delay=2)
def fetch_data_from_api(url):
# ... логика запроса
pass
Ключевой момент: Когда вы пишете @retry(max_attempts=5), сначала вызывается retry(max_attempts=5), который возвращает сам декоратор (decorator). Затем этот декоратор применяется к функции (fetch_data_from_api), как если бы он был обычным декоратором без аргументов.