← Назад к вопросам

К чему может быть применен декоратор

2.0 Middle🔥 191 комментариев
#Python Core

Комментарии (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) без повторения кода.