In Python zijn decorators sinds versie 2.4 onderdeel van de taal en bieden ze de mogelijkheid om het gedrag van functies en klassen te wijzigen. Decorators voor functieparameters zijn een complexer patroon dat handmatig wordt geïmplementeerd, omdat er geen directe syntactische ondersteuning voor dergelijke decorators in de taal is. Maar met behulp van annotaties en metaprogrammering kan hun functionaliteit worden gerealiseerd.
Gewone decorators beïnvloeden de gehele functie of methode. Soms is het nodig om alleen specifieke parameters van de functie te valideren, loggen of wijzigen op een bepaald abstractieniveau. Bijvoorbeeld, het type van het argument controleren, de waarde van de parameter converteren of beperkingen op de invoer opleggen.
Functieparameterdecorators worden gemaakt als metadata (bijvoorbeeld via type-annotaties) en worden verwerkt in een externe wrapper-decorator. De essentie van het patroon is om de benodigde informatie over de parameters op te slaan en vervolgens gebruikt de "functionele" decorator deze voor het verwerken van waarden bij het aanroepen van de functie.
Voorbeeldcode:
import inspect from functools import wraps def positive_param(fn): """Annotatie voor verplichte controle op de positiviteit van het argument.""" fn._positive = True return fn # Externe volledige 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} moet positief zijn") return func(*args, **kwargs) return wrapper @validate_decorator def deposit(amount: positive_param): print(f"Gestort {amount}") deposit(10) # OK deposit(-5) # ValueError
Belangrijke eigenschappen:
Hoe verschillen functieparameterdecorators van standaard functionele decorators?
Een standaarddecorator omhult de gehele functie, ongeacht de parameters. Een parameterdecorator richt zich op een specifiek argument en wordt alleen daarop toegepast, wat ongebruikelijke technieken voor verwerking en analyse van de handtekening vereist.
Kunnen parameterdecorators worden geïmplementeerd via de @ syntaxis in Python, zoals dit gebeurt in TypeScript of C#?
Nee, in Python wordt de decorator-syntaxis via @ alleen toegepast op functies en klassen, maar niet op individuele parameters van een functie. Voor parameters worden annotaties gebruikt, en vervolgens - de verwerking van annotaties bij het omhulsel van de functie.
Kunnen decorators automatisch op de parameters van functieargumenten worden toegepast zonder expliciete annotatie?
Nee, Python past decorators niet automatisch op parameters toe, maar je kunt een eigen mechanisme implementeren, zoals een op maat gemaakte decorator-fabriek die de handtekening van de functie analyseert en de waarden van de parameters vervangt bij het aanroepen.
Een ontwikkelaar is ervan overtuigd dat je @ op een parameter kunt gebruiken, zoals in andere talen, en schrijft:
def f(@validate_positive x): ...
Pluspunten:
Minpunten:
De ontwikkelaar gebruikt een annotatie en externe decorator, zoals in het bovenstaande voorbeeld, en verwerkt de parameters via de handtekening en annotaties:
Pluspunten:
Minpunten: