def logger(func):
def wrapper(*args, **kwargs):
print(f»Вызов функции {func.__name__}»)
return func(*args, **kwargs)
return wrapper
@logger
def greet(name):
return f»Привет, {name}!»
print(greet(«Мир»))
2. Декоратор с аргументами
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def say_hello():
print(«Hello!»)
say_hello()
3. Кеширование с 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(100))
4. Декоратор для замера времени
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
print(f»Время выполнения: {end — start:.4f} сек.»)
return result
return wrapper
@timer
def slow_function():
time.sleep(2)
slow_function()
5. Декораторы в классах
class Debugger:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print(f»Отладка: {self.func.__name__}»)
return self.func(*args, **kwargs)
@Debugger
def multiply(a, b):
return a * b
print(multiply(5, 6))
6. Декораторы для проверки прав доступа
Декораторы отлично подходят для контроля доступа в веб-приложениях. Например, можно ограничить выполнение функции только для авторизованных пользователей:
def login_required(func):
def wrapper(user, *args, **kwargs):
if not user.get(«is_authenticated»):
raise PermissionError(«Требуется авторизация»)
return func(user, *args, **kwargs)
return wrapper
@login_required
def view_profile(user):
return f»Профиль: {user[‘name’]}»
user = {«name»: «Alice», «is_authenticated»: True}
print(view_profile(user))
7. Декораторы с параметрами и functools.wraps
Чтобы сохранить исходные метаданные функции (например, __name__
, __doc__
), используют functools.wraps
:
from functools import wraps
def deprecated(message):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f»Внимание: {func.__name__} устарела. {message}»)
return func(*args, **kwargs)
return wrapper
return decorator
@deprecated(«Используйте новую функцию ‘calculate_v2′»)
def calculate(x, y):
«»»Возвращает сумму двух чисел.»»»
return x + y
print(calculate(2, 3))
print(calculate.__name__)
print(calculate.__doc__)
8. Декораторы для асинхронных функций
Декораторы также работают с async/await
:
import asyncio
def async_timer(func):
async def wrapper(*args, **kwargs):
start = time.perf_counter()
result = await func(*args, **kwargs)
end = time.perf_counter()
print(f»Асинхронная функция выполнилась за {end — start:.2f} сек.»)
return result
return wrapper
@async_timer
async def fetch_data():
await asyncio.sleep(1)
return «Данные получены»
asyncio.run(fetch_data())
9. Несколько декораторов на одной функции
Декораторы применяются снизу вверх (ближайший к функции выполняется первым):
def bold(func):
def wrapper():
return f»<b>{func()}</b>»
return wrapper
def italic(func):
def wrapper():
return f»<i>{func()}</i>»
return wrapper
@bold
@italic
def hello():
return «Привет, мир!»
print(hello())
10. Декораторы в промышленной разработке
В реальных проектах декораторы часто используются для:
-
Валидации аргументов (@validate_input
)
-
Ретри-логики (@retry_on_failure
)
-
Транзакций БД (@transactional
)
-
Лимитирования запросов (@rate_limit
)
Пример декоратора для повторного выполнения функции при ошибке:
import random
from time import sleep
def retry(max_attempts=3, delay=1):
def decorator(func):
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts — 1:
raise
sleep(delay)
return wrapper
return decorator
@retry(max_attempts=5)
def unstable_operation():
if random.random() < 0.7:
raise ValueError(«Ошибка!»)
return «Успех»
print(unstable_operation())
Заключение:
Декораторы в Python — это не просто синтаксическая особенность языка, а мощный паттерн проектирования, который открывает двери в мир чистого, модульного и поддерживаемого кода. Они позволяют:
✅ Уменьшить дублирование — выносим общую логику в декораторы
✅ Делать код читаемее — функциональность становится декларативной
✅ Легко масштабировать — новые возможности добавляются без изменения исходного кода
✅ Следовать принципам SOLID — особенно принципу открытости/закрытости
✅ Использовать лучшие практики — кеширование, логирование, обработка ошибок
Главная сила декораторов — в их универсальности. Они одинаково полезны как в небольших скриптах, так и в крупных проектах, где важны чистая архитектура и производительность.
Для Дальнейшего Изучения
-
Встроенные декораторы Python — углублённое изучение @property
, @classmethod
, @staticmethod
-
Декораторы с сохранением состояния — как использовать замыкания и классы для более сложной логики
-
Декораторы в популярных фреймворках — @app.route
во Flask, @login_required
в Django
-
Метапрограммирование — как создавать декораторы, которые принимают другие декораторы
-
Оптимизация производительности — @lru_cache
, @numba.jit
и их аналоги
-
Асинхронные декораторы — работа с async/await
и конкурентным выполнением
-
Тестирование декораторов — как правильно писать unit-тесты для сложных декораторов