In Python ermöglicht der Dekorator @property das Erstellen von "virtuellen" Attributen — Methoden, die wie normale Felder aussehen und verwendet werden, aber die Logik von Getter, Setter oder Deleter ausführen. Dies ist praktisch für die Erstellung von berechneten Eigenschaften oder die Kontrolle des Zugriffs auf Daten.
Beispiel:
class Rectangle: def __init__(self, width, height): self._width = width self._height = height @property def area(self): return self._width * self._height @property def width(self): return self._width @width.setter def width(self, value): if value <= 0: raise ValueError('Width must be positive') self._width = value r = Rectangle(3, 4) print(r.area) # 12 (wird wie eine Eigenschaft, nicht als Funktion aufgerufen) r.width = 10 # Setter wird automatisch aufgerufen
Kann man nur einen @property (Get-Methode) verwenden, ohne einen Setter zu definieren? Was passiert, wenn man versucht, ein solches Attribut zu ändern?
Antwort: Man kann nur den Getter @property ohne Setter (und Deleter) definieren. Dieses Attribut wird schreibgeschützt sein, ein Zuweisungsversuch wird einen AttributeError auslösen.
class C: @property def x(self): return 42 c = C() c.x = 99 # AttributeError: can't set attribute
Geschichte
Wir haben versucht, ein Objekt mit der Standardbibliothek zu serialisieren, indem wir vars(obj) verwendet haben, um ein Wörterbuch der Attribute zu erhalten. Es stellte sich heraus, dass property-Methoden nicht im Ausgabe von __dict__ enthalten sind, ihre Werte wurden nicht serialisiert, was zu einem Datenleck führte.
Geschichte
Im Projekt wurde vergessen, einen Setter für die property hinzuzufügen, was dazu führte, dass der Versuch, den Wert eines berechneten Feldes zu ändern, zu einem Laufzeitfehler führte, obwohl dies architektonisch erwartet wurde.
Geschichte
Im funktionierenden Code erlaubte die Berechnung des Wertes der property schwere oder unsichere Operationen, die unerwartet bei jedem Zugriff auf die Eigenschaft aufgerufen wurden. Dies verringerte die Leistung und führte zu blockierenden Aufrufen im mehrfädigen Code.