В Python декораторы стали частью языка с версии 2.4, обеспечивая возможность модифицировать поведение функций и классов. Декораторы для параметров функций — это более сложный паттерн, который реализуют вручную, поскольку прямой синтаксической поддержки таких декораторов в языке нет. Но с помощью аннотаций и метапрограммирования можно реализовать их функциональность.
Обычные декораторы воздействуют на всю функцию или метод. Иногда требуется валидировать, логировать или изменять только отдельные параметры функции на определённом уровне абстракции. Например, проверить тип аргумента, преобразовать значение параметра или наложить ограничения на ввод.
Декораторы параметров функций создаются как метаданные (например, через аннотации типов) и обрабатываются во внешнем обёртывающем декораторе. Суть паттерна — сохранить нужную информацию о параметрах, а затем "функциональный" декоратор использует её для обработки значений при вызове функции.
Пример кода:
import inspect from functools import wraps def positive_param(fn): """Аннотация для обязательной проверки положительности аргумента.""" fn._positive = True return fn # Внешний полноценный декоратор def validate_decorator(func): spec = inspect.getfullargspec(func) @wraps(func) def wrapper(*args, **kwargs): bound_args = inspect.signature(func).bind(*args, **kwargs) for name, value in bound_args.arguments.items(): param = func.__annotations__.get(name, None) if getattr(param, '_positive', False) and value <= 0: raise ValueError(f"Argument {name} must be positive") return func(*args, **kwargs) return wrapper @validate_decorator def deposit(amount: positive_param): print(f"Deposited {amount}") deposit(10) # OK deposit(-5) # ValueError
Ключевые особенности:
Чем декораторы параметров отличаются от стандартных декораторов функций?
Стандартный декоратор оборачивает всю функцию, независимо от параметров. Декоратор параметра фокусируется на конкретном аргументе и применяется только к нему, что требует нестандартных техник обработки и анализа сигнатуры.
Могут ли декораторы параметров реализовываться через синтаксис @ в Python, как это делается в TypeScript или C#?
Нет, в Python синтаксис декораторов через @ применяется только к функциям и классам, но не к отдельным параметрам функции. Для параметров используют аннотации, а затем — обработку аннотаций при обёртывании функции.
Можно ли автоматически применять декораторы к параметрам аргументов функции без явной аннотации?
Нет, Python не применяет к параметрам декораторы автоматически, но можно реализовать собственный механизм, например через пользовательскую фабрику декораторов, которая будет анализировать сигнатуру функции и подменять значения параметров при вызове.
Разработчик уверен, что можно использовать @ на параметре, как в других языках, и пишет:
def f(@validate_positive x): ...
Плюсы:
Минусы:
Разработчик использует аннотацию и внешний декоратор, как в примере выше, и обрабатывает параметры через сигнатуру и аннотации:
Плюсы:
Минусы: