Перейти к содержанию
  • Лента
  • Категории
  • Последние
  • Метки
  • Популярные
  • Пользователи
  • Группы
Свернуть
exlends
Категории
  1. Главная
  2. Категории
  3. Языки программирования
  4. Python
  5. Python декораторы: простое объяснение с примерами и кодом

Python декораторы: простое объяснение с примерами и кодом

Запланировано Прикреплена Закрыта Перенесена Python
pythonдекораторыфункции
1 Сообщения 1 Постеры 2 Просмотры
  • Сначала старые
  • Сначала новые
  • По количеству голосов
Ответить
  • Ответить, создав новую тему
Авторизуйтесь, чтобы ответить
Эта тема была удалена. Только пользователи с правом управления темами могут её видеть.
  • hannadevH Не в сети
    hannadevH Не в сети
    hannadev
    написал отредактировано
    #1

    Декораторы в Python — это мощный инструмент для расширения функций без изменения их кода. Они позволяют добавлять логику вроде логирования, кэширования или проверки доступа, делая код чище и повторно используемым.

    Зачем они нужны? Представь, что у тебя есть функция для вычисления, и ты хочешь каждый раз измерять её время или логировать вызовы. Вместо копипасты кода везде просто пишешь декоратор и вешаешь его одной строкой. Это решает проблему дублирования и упрощает поддержку.

    Что такое декоратор на самом деле

    Декоратор — это функция, которая принимает другую функцию как аргумент, оборачивает её в новую логику и возвращает обновлённую версию. Всё происходит автоматически с помощью синтаксиса @имя_декоратора. Это как обёртка: внешний слой добавляет поведение, а внутри остаётся оригинальная функция.

    Рассмотрим базовый пример. Допустим, у нас есть простая функция say_hi, которая возвращает строку “всем привет”. Декоратор сделает буквы заглавными, не трогая код функции. Оборачиваем функцию во внутреннюю wrapper, выполняем нужную логику до и после вызова оригинала — и готово. Такой подход работает для любых функций, даже с параметрами.

    Вот как выглядит структура:

    • Декоратор принимает func.
    • Внутри создаёт wrapper, которая вызывает func с аргументами.
    • Wrapper возвращает результат func плюс добавленная логика.
    def uppercase_decorator(func):
        def wrapper():
            result = func()
            return result.upper()
        return wrapper
    
    @uppercase_decorator
    def say_hi():
        return "всем привет"
    
    print(say_hi())  # ВСЕМ ПРИВЕТ
    

    Ключевой момент: *wrapper должна принимать *args и *kwargs, чтобы декоратор работал с любыми функциями.

    Простые примеры декораторов в действии

    Начнём с логирования. Представь функцию, которая печатает имя. Декоратор перед вызовом выведет “Функция вызвана”. Это полезно для отладки: видишь стек вызовов без if-ов повсюду. Аналогично можно добавить timestamp или уровень логирования.

    Другой пример — замер времени. Функция вычисляет сумму списка, а декоратор покажет, сколько прошло миллисекунд. Импортируешь time, фиксируешь start и end в wrapper — и вуаля. Идеально для оптимизации кода.

    Переходим к деталям. Вот типичные случаи:

    • Логирование: print(f"Вызвана {func.name}")
    • Время выполнения: time.perf_counter() до и после
    • Проверка аргументов: raise ValueError, если не ок
    Пример декоратора Что добавляет Когда использовать
    Логирование Сообщение о вызове Отладка, мониторинг
    Тайминг Время в мс Профилирование
    Кэширование Сохранение результата Дорогие вычисления

    Эти примеры показывают, как декораторы упрощают жизнь. Не забывай возвращать результат func, иначе функция ничего не отдаст.

    Декораторы с параметрами и несколько штук сразу

    Обычный декоратор не принимает аргументы сам по себе. Чтобы добавить параметры, создай фабрику: внешняя функция принимает настройки, внутри — настоящий декоратор с wrapper. Например, декоратор повторений: @retry(times=3) — попробует функцию 3 раза при ошибке.

    С несколькими декораторами порядок важен. Они применяются снизу вверх: первый ближе к функции оборачивает её, следующий — результат предыдущего. Если @log над @time, то сначала time, потом log. Это накапливает эффекты: время + лог + валидация.

    Структура декоратора с параметрами:

    1. Внешняя функция repeat(n):
    2. Возвращает decorator(func)
    3. Decorator возвращает wrapper с циклом на n попыток
    4. Wrapper ловит исключения и retry
    def repeat(n):
        def decorator(func):
            def wrapper(*args, **kwargs):
                for _ in range(n):
                    try:
                        return func(*args, **kwargs)
                    except:
                        pass
                raise
            return wrapper
        return decorator
    
    @repeat(3)
    def risky_func():
        # может упасть
        pass
    

    Важно: сохраняй метаданные func с functools.wraps(func) — имя, докстринг останутся правильными.

    Декораторы на классах и продвинутые фичи

    Не только функции: классы с init и call тоже декораторы. В init сохраняешь func, в call — выполняешь логику. Полезно для состояний, как счётчик вызовов или кэш в атрибуте.

    Применение: мемоизация. Декоратор хранит результаты в словаре {args: result}. При повторном вызове с теми же аргументами — берёт из кэша. Идеально для рекурсии Фибоначчи или API-запросов.

    Продвинутые примеры:

    • Мемоизация: @lru_cache из functools
    • Состояние в классе: self.count +=1
    • Для методов: self-aware wrapper
    Тип декоратора Преимущества Ограничения
    Функция Просто Нет состояния
    Класс Состояние Словеснее
    functools Готовые Меньше контроля

    Классовые декораторы хороши, когда нужна память между вызовами.

    Когда декораторы меняют правила игры

    Декораторы — это не просто сахар: они принцип SOLID в действии. Модифицируешь поведение без изменения класса или функции, делая код модульным. В веб-фреймворках вроде Flask они проверяют роли, в тестах — мокнут зависимости.

    Осталось место для размышлений: как комбинировать с async/await или генераторами? Или создать декоратор для валидации схем с pydantic. Подумай над своими проектами — наверняка найдётся, где упростить логику.

    Это базовый набор, чтобы стартовать уверенно. Дальше экспериментируй с реальными задачами.

    1 ответ Последний ответ
    0

    Категории

    • Главная
    • Новости
    • Фронтенд
    • Бекенд
    • Языки программирования

    Контакты

    • Сотрудничество
    • info@exlends.com
    • Наш чат
    • Наш ТГ канал

    © 2024 - 2025 ExLends, Inc. Все права защищены.

    Политика конфиденциальности
    • Войти

    • Нет учётной записи? Зарегистрироваться

    • Войдите или зарегистрируйтесь для поиска.
    • Первое сообщение
      Последнее сообщение
    0
    • Лента
    • Категории
    • Последние
    • Метки
    • Популярные
    • Пользователи
    • Группы