In Python, decorators became part of the language starting from version 2.4, providing the ability to modify the behavior of functions and classes. Function parameter decorators are a more complex pattern that is implemented manually, as there is no direct syntactical support for such decorators in the language. However, their functionality can be achieved using annotations and metaprogramming.
Standard decorators affect the entire function or method. Sometimes, it is necessary to validate, log, or alter only specific parameters of a function at a certain level of abstraction. For example, to check the type of an argument, transform the value of a parameter, or impose constraints on input.
Function parameter decorators are created as metadata (e.g., via type annotations) and are processed within an external wrapping decorator. The essence of the pattern is to retain the necessary information about the parameters, which the "functional" decorator then uses to process the values upon calling the function.
Code example:
import inspect from functools import wraps def positive_param(fn): """Annotation for mandatory positivity check of the argument.""" fn._positive = True return fn # External full-fledged decorator 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
Key features:
How do parameter decorators differ from standard function decorators?
A standard decorator wraps the entire function, regardless of the parameters. A parameter decorator focuses on a specific argument and applies only to it, which requires unconventional techniques for processing and analyzing the signature.
Can parameter decorators be implemented through the @ syntax in Python, as it is done in TypeScript or C#?
No, in Python, the @ decorator syntax is applied only to functions and classes, not to individual function parameters. For parameters, annotations are used first, followed by processing of the annotations when wrapping the function.
Is it possible to automatically apply decorators to function argument parameters without explicit annotation?
No, Python does not automatically apply decorators to parameters, but you can implement your own mechanism, such as a custom decorator factory that analyzes the function signature and replaces parameter values when invoked.
A developer is confident that @ can be used on a parameter like in other languages and writes:
def f(@validate_positive x): ...
Pros:
Cons:
The developer uses an annotation and an external decorator, as in the example above, and processes parameters through the signature and annotations:
Pros:
Cons: