In Python erklären Descriptoren und gesteuerte Attribute, wie man Objekte besser strukturiert

In Python erklären Descriptoren und gesteuerte Attribute, wie man Objekte besser strukturiert
2 min de lecture

Die Deskriptoren von Python ermöglichen es zu steuern, was beim Lesen, Ändern oder Löschen eines Objektattributs geschieht. Ein Tutorial erläutert detailliert, wie man sie einsetzt, um drei Arten von gesteuerten Attributen zu konstruieren: validierte, berechnete und bei Bedarf geladene. Es veranschaulicht den Ansatz anhand eines fiktiven Beispiels einer Tourismus-App für Japan.

Ein Deskriptor ist eine Klasse, die Methoden wie __get__, __set__ oder __delete__ implementiert, die das Verhalten eines Attributs definieren. Nicht alle sind zwingend erforderlich. Die Methode __set_name__, eingeführt mit Python 3.6, teilt dem Deskriptor den Namen des zugeordneten Attributs mit, was es ermöglicht, den Wert im __dict__ des Elternobjekts ohne Namenskonflikte zu speichern. Laut Autor vermeidet dieser Ansatz, den Code mit Dekoratoren wie @property, Getters und Setters zu überfrachten.

Validierte, berechnete oder faule Attribute

Das erste Beispiel, genannt ValidatedRating, prüft, ob eine Bewertung eine Zahl (ganzzahlig oder dezimal) zwischen einem minimalen und einem maximalen Wert ist, standardmäßig auf 1.0 und 5.0 festgelegt. Bei einem nicht-numerischen Wert löst es eine TypeError aus; liegt der Wert außerhalb des Bereichs, eine ValueError.

Das zweite, ComputedUSDPrice, dient dazu, einen in japanischen Yen (JPY) gespeicherten Preis in US-Dollar anzuzeigen. Es berechnet die Umrechnung dynamisch basierend auf einem Wechselkurs von 0,0067, der im Code als Näherung angegeben ist. Da das Attribut schreibgeschützt ist, löst jeder Schreibversuch eine AttributeError aus.

Das dritte, LazyItinerary, gilt für Daten, deren Erzeugung aufwändig ist, wie das Lesen einer großen JSON-Datei oder die Abfrage einer Datenbank mit Fahrplänen der Shinkansen, der japanischen Hochgeschwindigkeitszüge. Der Deskriptor berechnet den Wert erst bei der ersten Abfrage, speichert ihn im __dict__ der Instanz und tritt dann zurück. Nachfolgende Abfragen lesen diesen Wert direkt. Im Beispiel ist eine Latenzsimulation von einer Sekunde enthalten.

Praktische Anwendung mit einem Besuch in Kyoto

Diese drei Deskriptoren werden in einer Klasse JapanTour zusammengeführt. Bei der Initialisierung mit einem Ziel « Kyoto », einem Preis von 45000 JPY und einer Bewertung von 4,8 wird die Validierung sofort ausgelöst. Als der Autor anschließend versucht, der Bewertung den Wert 6.0 zuzuweisen, wird die Exception abgefangen und die Meldung « rating must be between 1.0 and 5.0. » angezeigt.

Die erste Abfrage des Reiseplans zeigt die Simulationsmeldung der Anfrage an, dann ein dreitägiges Programm: Ankunft und Check-in in Kyoto, geführte Tempelbesichtigung und Street-Food-Verkostung, dann Abreise mit dem Shinkansen. Bei der zweiten Abfrage erscheint die Meldung nicht mehr: Der Wert wird direkt von der Instanz gelesen.

Der Artikel schließt damit, dass diese drei Arten von Deskriptoren die Robustheit von Klassenattributen stärken, indem sie jeweils die Datenintegrität sicherstellen, abgeleitete Werte berechnen und aufwändige Operationen verwalten.