Декораторы

Python

Классы-декораторы в Python

Основные концепции

1. Базовый класс-декоратор


class SimpleDecorator:
    def __init__(self, func):
        self.func = func  # Сохраняем декорируемую функцию

    def __call__(self, *args, **kwargs):
        print("Действие перед вызовом функции")
        result = self.func(*args, **kwargs)
        print("Действие после вызова функции")
        return result

@SimpleDecorator
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

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


class ParametrizedDecorator:
    def __init__(self, prefix=""):
        self.prefix = prefix  # Параметр декоратора

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            print(f"{self.prefix} Перед вызовом")
            result = func(*args, **kwargs)
            print(f"{self.prefix} После вызова")
            return result
        return wrapper

@ParametrizedDecorator(prefix="DEBUG:")
def calculate(a, b):
    return a + b

print(calculate(2, 3))

3. Сохранение метаданных функции


import functools

class MetadataPreservingDecorator:
    def __init__(self, func):
        self.func = func
        functools.wraps(func)(self)  # Сохраняем метаданные

    def __call__(self, *args, **kwargs):
        """Документация декоратора"""
        print("Дополнительная логика")
        return self.func(*args, **kwargs)

@MetadataPreservingDecorator
def example():
    """Оригинальная документация"""
    print("Функция выполнена")

print(example.__name__)  # example
print(example.__doc__)   # Оригинальная документация

Продвинутые техники

4. Декоратор методов класса


class MethodDecorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, instance, *args, **kwargs):
        print(f"Вызов метода {self.func.__name__} класса {instance.__class__.__name__}")
        return self.func(instance, *args, **kwargs)

class MyClass:
    @MethodDecorator
    def my_method(self):
        print("Метод выполнен")

obj = MyClass()
obj.my_method()

5. Декоратор с состоянием


class CounterDecorator:
    def __init__(self, func):
        self.func = func
        self.calls = 0

    def __call__(self, *args, **kwargs):
        self.calls += 1
        print(f"Функция вызвана {self.calls} раз")
        return self.func(*args, **kwargs)

@CounterDecorator
def say_hello():
    print("Hello!")

say_hello()
say_hello()

6. Декоратор с возможностью отключения


class SwitchableDecorator:
    def __init__(self, active=True):
        self.active = active

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            if self.active:
                print("Декоратор активен")
            return func(*args, **kwargs)
        return wrapper

@SwitchableDecorator(active=False)
def function():
    print("Функция выполнена")

function()

Важные моменты для собеседования

  1. Как работает декоратор?
    • Декоратор - это функция или класс, который принимает функцию и возвращает новую функцию
    • Синтаксис @decorator эквивалентен func = decorator(func)
  2. Разница между функцией-декоратором и классом-декоратором
    • Классы-декораторы полезны, когда нужно:
      • Сохранять состояние между вызовами
      • Реализовать сложную логику
      • Использовать ООП подход
  3. Почему functools.wraps важен?
    • Сохраняет оригинальное имя функции и документацию
    • Без него декорированная функция теряет свои метаданные
  4. Когда использовать классы-декораторы?
    • Когда нужен декоратор с состоянием
    • Для сложных декораторов с несколькими уровнями вложенности
    • Когда требуется повторно используемая логика декорирования

11 2025.04.07 08:43