Python Декораторы

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

Основы декораторов

  • Декораторы используют концепцию функций высшего порядка
  • Позволяют добавлять функциональность к существующим функциям
  • Применяются с помощью синтаксиса @decorator_name
  • Возвращают обёртку вокруг оригинальной функции

Пример простого декоратора

 1def my_decorator(func):
 2    def wrapper():
 3        print("Что-то происходит перед функцией")
 4        func()
 5        print("Что-то происходит после функции")
 6    return wrapper
 7
 8@my_decorator
 9def say_hello():
10    print("Привет!")
11
12say_hello()
13# Вывод:
14# Что-то происходит перед функцией
15# Привет!
16# Что-то происходит после функции

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

 1import functools
 2
 3def my_decorator(func):
 4    @functools.wraps(func)
 5    def wrapper(*args, **kwargs):
 6        print(f"Вызывается функция {func.__name__}")
 7        result = func(*args, **kwargs)
 8        print(f"Функция {func.__name__} завершена")
 9        return result
10    return wrapper
11
12@my_decorator
13def greet(name):
14    return f"Привет, {name}!"
15
16print(greet("Анна"))
17# Вывод:
18# Вызывается функция greet
19# Функция greet завершена
20# Привет, Анна!

Типы декораторов

  • Функциональные декораторы — декорируют функции
  • Классовые декораторы — декорируют классы
  • Встроенные декораторы — @property, @staticmethod, @classmethod
  • Декораторы с параметрами — принимают аргументы

Встроенные декораторы Python

 1class MyClass:
 2    def __init__(self, value):
 3        self._value = value
 4
 5    @property
 6    def value(self):
 7        """Превращает метод в атрибут"""
 8        return self._value
 9
10    @value.setter
11    def value(self, new_value):
12        self._value = new_value
13
14    @staticmethod
15    def static_method():
16        """Статический метод класса"""
17        return "Статический метод"
18
19    @classmethod
20    def class_method(cls):
21        """Метод класса"""
22        return f"Метод класса {cls.__name__}"

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

 1def repeat(times):
 2    def decorator(func):
 3        @functools.wraps(func)
 4        def wrapper(*args, **kwargs):
 5            for _ in range(times):
 6                result = func(*args, **kwargs)
 7            return result
 8        return wrapper
 9    return decorator
10
11@repeat(3)
12def say_hello():
13    print("Привет!")
14
15say_hello()
16# Вывод:
17# Привет!
18# Привет!
19# Привет!

Практические применения декораторов

  • Логирование — запись информации о вызове функций
  • Аутентификация — проверка прав доступа
  • Кеширование — сохранение результатов вычислений
  • Измерение времени — профилирование производительности
  • Валидация — проверка входных параметров

Пример декоратора для измерения времени

 1import time
 2import functools
 3
 4def timing(func):
 5    @functools.wraps(func)
 6    def wrapper(*args, **kwargs):
 7        start_time = time.time()
 8        result = func(*args, **kwargs)
 9        end_time = time.time()
10        print(f"{func.__name__} выполнилась за {end_time - start_time:.4f} секунд")
11        return result
12    return wrapper
13
14@timing
15def slow_function():
16    time.sleep(1)
17    return "Готово"
18
19slow_function()
20# Вывод: slow_function выполнилась за 1.0012 секунд

FAQ

Когда использовать декораторы?

Для логирования, аутентификации, кеширования, измерения времени выполнения и других сквозных задач, которые не относятся к основной логике функции.

Зачем нужен @functools.wraps?

@functools.wraps сохраняет метаданные оригинальной функции (имя, документацию), что важно для отладки и интроспекции.