Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Применение декораторов в Python
Декоратор — это функция, которая принимает другую функцию и модифицирует её поведение, не изменяя исходный код.
1. Декоратор функции (функция обёрнута в функцию)
Мост используемый вариант.
def my_decorator(func):
"""Декоратор, который логирует вызов функции"""
def wrapper(*args, **kwargs):
print(f"Вызов: {func.__name__}({args}, {kwargs})")
result = func(*args, **kwargs)
print(f"Результат: {result}")
return result
return wrapper
@my_decorator
def add(a, b):
"""Складывает два числа"""
return a + b
add(2, 3)
# Вывод:
# Вызов: add((2, 3), {})
# Результат: 5
2. Декоратор с параметрами
Декоратор может принимать аргументы.
def repeat(times):
"""Повторяет выполнение функции N раз"""
def decorator(func):
def wrapper(*args, **kwargs):
results = []
for _ in range(times):
result = func(*args, **kwargs)
results.append(result)
return results
return wrapper
return decorator
@repeat(3)
def greet(name):
return f"Привет, {name}!"
print(greet("Иван"))
# ["Привет, Иван!", "Привет, Иван!", "Привет, Иван!"]
3. Декоратор класса
Декораторы применяются к классам целиком.
def add_repr(cls):
"""Автоматически добавляет __repr__"""
def __repr__(self):
attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())
return f"{cls.__name__}({attrs})"
cls.__repr__ = __repr__
return cls
@add_repr
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Алиса", 30)
print(p) # Person(name=Алиса, age=30)
4. Декоратор метода
def logged(func):
"""Логирует вызовы методов"""
def wrapper(self, *args, **kwargs):
print(f"Вызов метода {func.__name__} для {self}")
return func(self, *args, **kwargs)
return wrapper
class Calculator:
@logged
def multiply(self, a, b):
return a * b
calc = Calculator()
calc.multiply(2, 3) # Вывод: Вызов метода multiply для <Calculator object>
5. Встроенные декораторы Python
@property - превращает метод в свойство
class User:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
user = User("Иван")
print(user.name) # "Иван" (вызов как свойство, не метод)
user.name = "Петр" # Использование setter
@staticmethod - статический метод
class Math:
@staticmethod
def add(a, b):
"""Не нужен self"""
return a + b
print(Math.add(2, 3)) # 5
@classmethod - метод класса
class Animal:
species = "Unknown"
@classmethod
def change_species(cls, new_species):
"""Получает класс, а не объект"""
cls.species = new_species
Animal.change_species("Mammal")
print(Animal.species) # "Mammal"
6. Практические применения
Кэширование результатов (Memoization)
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
"""Кэширует результаты для избежания пересчёта"""
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(100)) # Быстро благодаря кэшу
Валидация аргументов
def validate_positive(func):
"""Проверяет, что все аргументы положительные"""
def wrapper(*args, **kwargs):
for arg in args:
if isinstance(arg, (int, float)) and arg < 0:
raise ValueError(f"Аргумент не может быть отрицательным: {arg}")
return func(*args, **kwargs)
return wrapper
@validate_positive
def divide(a, b):
return a / b
divide(10, 2) # OK
divide(-10, 2) # ValueError
Обработка исключений
def safe_execute(func):
"""Обрабатывает исключения"""
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
print(f"Ошибка в {func.__name__}: {e}")
return None
return wrapper
@safe_execute
def risky_operation():
return 1 / 0
risky_operation() # Ошибка в risky_operation: division by zero
Замер времени выполнения
import time
def timer(func):
"""Измеряет время выполнения"""
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} выполнилась за {end - start:.4f} сек")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
return "Готово"
slow_function() # slow_function выполнилась за 1.0001 сек
Проверка авторизации (например, в веб-фреймворке)
from functools import wraps
def require_auth(func):
"""Проверяет авторизацию перед выполнением"""
@wraps(func) # Сохраняет оригинальные метаданные функции
def wrapper(*args, **kwargs):
if not is_authenticated(): # Условная проверка
raise PermissionError("Требуется авторизация")
return func(*args, **kwargs)
return wrapper
@require_auth
def get_user_profile():
return "Профиль пользователя"
7. Важные моменты
Используй functools.wraps для сохранения метаданных
from functools import wraps
def my_decorator(func):
@wraps(func) # Важно!
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@my_decorator
def important_function():
"""Важная функция"""
pass
print(important_function.__name__) # "important_function" (не "wrapper")
print(important_function.__doc__) # "Важная функция"
Итоговая таблица применений
| Применение | Пример | Назначение |
|---|---|---|
| Логирование | @logger | Отслеживать вызовы |
| Кэширование | @lru_cache | Ускорить вычисления |
| Валидация | @validate | Проверка входных данных |
| Авторизация | @require_auth | Контроль доступа |
| Профилирование | @timer | Замер производительности |
| Property | @property | Контролируемый доступ к атрибутам |
| Сериализация | @dataclass | Автогенерация методов |
| API маршруты | @app.route() | Flask/Django маршруты |
Декораторы — мощный инструмент для кросс-функционального функционала (logging, timing, validation) без повторения кода.