Een descriptor is een object dat een van de methoden get, set en delete implementeert. Het stelt je in staat de toegang tot de attributen van een klasse te controleren.
Standaardmethoden van de descriptor:
__get__(self, instance, owner)__set__(self, instance, value)__delete__(self, instance)Descriptors zijn:
Voorbeeld van gebruik:
class OnlyPositive: def __init__(self): self._name = '_value' def __get__(self, instance, owner): return instance.__dict__[self._name] def __set__(self, instance, value): if value < 0: raise ValueError('Waarde moet >= 0 zijn') instance.__dict__[self._name] = value class Account: value = OnlyPositive() def __init__(self, value): self.value = value acc = Account(10) acc.value = -1 # ValueError!
property is slechts syntactische suiker voor het maken van descriptors op klasseniveau.
Wat gebeurt er als je een descriptor als een attribuut van een instantie maakt, en niet van de klasse?
Velen denken dat de descriptor zal werken, maar dat is niet het geval.
Correct antwoord:
Een descriptor werkt alleen als deze rechtstreeks als een attribuut van de klasse is gedefinieerd. Als de descriptor als een attribuut van een instantie wordt ingesteld, worden de methoden get/set niet aangeroepen — de gebruikelijke logica voor het toegang krijgen tot een attribuut.
Verhaal
Het gebruik van property in plaats van een volledige descriptor
Voor validatie en andere gerelateerde attributen gebruikte de ontwikkelaar een eenvoudige property, wat leidde tot frequente duplicatie van logica en de onmogelijkheid om code tussen verschillende klassen te hergebruiken.
Verhaal
Het niet naleven van immutabiliteit bij hergebruik van opslag
De descriptor bewaarde gegevens in een intern attribuut van zijn eigen klasse (self.x), en niet in de interne opslag van de instantie, waardoor het attribuut "gemeenschappelijk" werd en verschillende instanties van de klasse elkaars waarden overschreven — gegevens "lekten" tussen objecten.
Verhaal
Data descriptor en non-data descriptor verwisseld
In een complexe hiërarchie werd de implementatie van set overgeslagen, waardoor een gewoon attribuut van een instantie de descriptor overschreef, wat het hele validatiemechanisme brak — de bug manifesteerde zich niet altijd, en het was moeilijk om te debuggen.