Ein Deskriptor ist ein Objekt, das eine der Methoden get, set und delete implementiert. Er ermöglicht die Kontrolle des Zugriffs auf die Attribute einer Klasse.
Standardmethoden des Deskriptors:
__get__(self, instance, owner)__set__(self, instance, value)__delete__(self, instance)Deskriptoren können sein:
Ein Beispiel für die Verwendung:
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('Der Wert muss >= 0 sein') instance.__dict__[self._name] = value class Account: value = OnlyPositive() def __init__(self, value): self.value = value acc = Account(10) acc.value = -1 # ValueError!
property ist nur syntaktischer Zucker zur Erstellung von Deskriptoren auf Klassenebene.
Was passiert, wenn man einen Deskriptor als Attribut einer Instanz und nicht einer Klasse erstellt?
Viele glauben, dass der Deskriptor funktionieren würde, aber das ist nicht der Fall.
Die richtige Antwort:
Ein Deskriptor funktioniert nur, wenn er direkt als Attribut der Klasse definiert ist. Wenn ein Deskriptor als Attribut einer Instanz festgelegt wird, werden die Methoden get/set nicht aufgerufen — es erfolgt der normale Zugriff auf das Attribut.
Geschichte
Verwendung von property anstelle eines vollwertigen Deskriptors
Für die Validierung und andere verwandte Attribute verwendete der Entwickler eine einfache property, was zu häufigen doppelten Logiken und der Unmöglichkeit führte, den Code zwischen verschiedenen Klassen wiederzuverwenden.
Geschichte
Nichteinhaltung der Immutabilität bei der Wiederverwendung von Speicher
Der Deskriptor speicherte Daten in einem internen Attribut seiner eigenen Klasse (self.x) und nicht im internen Speicher der Instanz, wodurch das Attribut "gemeinsam" wurde und verschiedene Instanzen der Klasse sich gegenseitig überschrieben — Daten "leakten" zwischen Objekten.
Geschichte
Verwechslung von data descriptor und non-data descriptor
In einer komplexen Hierarchie wurde die Implementierung von set übersehen, weshalb das normale Attribut der Instanz den Deskriptor überschritt und den gesamten Validierungsmechanismus störte — der Bug trat nicht immer auf und war schwer zu debuggen.