W Pythonie dekoratory stały się częścią języka od wersji 2.4, zapewniając możliwość modyfikowania zachowania funkcji i klas. Dekoratory dla parametrów funkcji to bardziej złożony wzorzec, który realizuje się ręcznie, ponieważ język nie ma bezpośredniego wsparcia syntaktycznego dla takich dekoratorów. Jednak za pomocą adnotacji i metaprogramowania można zrealizować ich funkcjonalność.
Zwykłe dekoratory wpływają na całą funkcję lub metodę. Czasami konieczne jest walidowanie, rejestrowanie lub zmienianie tylko poszczególnych parametrów funkcji na określonym poziomie abstrakcji. Na przykład, należy sprawdzić typ argumentu, przekształcić wartość parametru lub nałożyć ograniczenia na wejście.
Dekoratory parametrów funkcji są tworzone jako metadane (np. przez adnotacje typów) i przetwarzane w zewnętrznym opakowującym dekoratorze. Istota wzorca polega na zachowaniu odpowiednich informacji o parametrach, a następnie dekorator "funkcjonalny" wykorzystuje je do przetwarzania wartości podczas wywoływania funkcji.
Przykład kodu:
import inspect from functools import wraps def positive_param(fn): """Adnotacja do obowiązkowej weryfikacji pozytywności argumentu.""" fn._positive = True return fn # Zewnętrzny pełnoprawny dekorator 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} musi być pozytywny") return func(*args, **kwargs) return wrapper @validate_decorator def deposit(amount: positive_param): print(f"Wpłacono {amount}") deposit(10) # OK deposit(-5) # ValueError
Kluczowe cechy:
Czym różnią się dekoratory parametrów od standardowych dekoratorów funkcji?
Standardowy dekorator owija całą funkcję, niezależnie od parametrów. Dekorator parametru koncentruje się na konkretnym argumencie i stosuje się tylko do niego, co wymaga niestandardowych technik przetwarzania i analizy sygnatury.
Czy dekoratory parametrów mogą być realizowane za pomocą składni @ w Pythonie, tak jak w TypeScript lub C#?
Nie, w Pythonie składnia dekoratorów za pomocą @ jest stosowana tylko do funkcji i klas, ale nie do poszczególnych parametrów funkcji. Dla parametrów używa się adnotacji, a następnie przetwarzania adnotacji podczas opakowywania funkcji.
Czy można automatycznie stosować dekoratory do parametrów argumentów funkcji bez wyraźnej adnotacji?
Nie, Python nie stosuje dekoratorów automatycznie do parametrów, ale można zrealizować własny mechanizm, na przykład przez niestandardową fabrykę dekoratorów, która analizuje sygnaturę funkcji i zastępuje wartości parametrów podczas wywołania.
Programista jest przekonany, że można używać @ na parametrze, jak w innych językach, i pisze:
def f(@validate_positive x): ...
Zalety:
Wady:
Programista używa adnotacji i zewnętrznego dekoratora, jak w powyższym przykładzie, i przetwarza parametry przez sygnaturę i adnotacje:
Zalety:
Wady: