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 сохраняет метаданные оригинальной функции (имя, документацию), что важно для отладки и интроспекции.