Декораторы в Python: от простых к сложным

Мы просто и по делу рассказываем про ИИ-инструменты для работы: сравнения, пошаговые гайды, бесплатные альтернативы и реальные сценарии применения. Помогаем выбрать между ChatGPT, Gemini, Claude, локальными моделями и десятками узкоспециализированных сервисов — от дизайна и HR до аналитики и SEO. Меньше хайпа, больше практики и экономии времени каждый день.

декораторыpythonfunctools

Декораторы в Python — это способ изменять поведение функции или класса без правки их исходного кода. Если вы встречали @staticmethod, @classmethod или @login_required, значит уже работали с декораторами.

Почему тема важна:

  • помогают переиспользовать код
  • убирают дублирование
  • удобны для логирования, кэширования, проверки прав доступа, замера времени выполнения

Что такое декоратор

По сути, декоратор — это функция, которая принимает другую функцию и возвращает новую.

Простой пример:

def decorator(func):
    def wrapper():
        print("До вызова функции")
        func()
        print("После вызова функции")
    return wrapper

@decorator
def hello():
    print("Привет!")

hello()

Это аналогично записи:

hello = decorator(hello)

Как это работает

Когда Python видит @decorator, он:

  • берет функцию hello
  • передает ее в decorator
  • сохраняет результат обратно в hello

То есть вызывается уже не исходная функция, а обертка wrapper.

Декораторы с аргументами

Если функция принимает параметры, обертка тоже должна их принимать:

def decorator(func):
    def wrapper(*args, **kwargs):
        print("Запуск функции")
        result = func(*args, **kwargs)
        print("Функция завершена")
        return result
    return wrapper

*args и **kwargs делают декоратор универсальным — это стандартная практика. ✅

Важный момент: metadata функции

Без дополнительных действий декоратор “ломает” имя и docstring исходной функции. Для этого используют functools.wraps:

from functools import wraps

def decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

Это особенно важно в больших проектах, тестах и фреймворках.

Декораторы с параметрами

Иногда нужно передать настройки в сам декоратор. Тогда появляется еще один уровень вложенности:

from functools import wraps

def repeat(n):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for _ in range(n):
                func(*args, **kwargs)
        return wrapper
    return decorator

@repeat(3)
def greet():
    print("Hi")

Здесь repeat(3) сначала создает декоратор, а уже потом он оборачивает функцию.

Где применяются на практике

  • Логирование — фиксировать вызовы функций
  • Кэширование — например, через @lru_cache 🚀
  • Авторизация — проверка доступа пользователя
  • Измерение времени — профилирование медленных участков
  • Повторные попытки — retry при сетевых ошибках

Частые ошибки

  • забывают return result
  • не используют wraps
  • пишут декоратор без *args, **kwargs, из-за чего он работает только для одной сигнатуры
  • слишком усложняют логику, превращая код в “матрешку” 🤯

Итог

Декораторы — это не “магия Python”, а удобный инструмент для расширения поведения кода. Начинать стоит с простых оберток, затем переходить к параметризованным декораторам и встроенным решениям вроде @wraps и @lru_cache. Понимание декораторов особенно важно для backend-разработки, автоматизации и работы с фреймворками Django/FastAPI. 🔧💡

📌 Ниже стоит посмотреть подборку каналов про IT — там много полезного по Python, backend и разработке в целом.

🗣 Подборки каналов
🧠 Каталог ботов и приложений
🗺 Навигация

Читайте так же