Heim > Artikel > Backend-Entwicklung > Schwierige Verwendung von @property decorator in Python (Codebeispiel)
In diesem Artikel geht es um die technische Verwendung des @property-Dekorators in Python (Codebeispiele). Ich hoffe, dass er für Sie hilfreich ist.
Der @property decorator kann eine Methode in eine Eigenschaft umwandeln und sie aufrufen. Werfen wir einen Blick auf die Analyse der Verwendungsfähigkeiten des @property decorators in Python.
@ Wofür werden Attribute verwendet? ? Oberflächlich betrachtet scheint es, dass auf eine Methode als Attribut zugegriffen wird.
Der obige Code
class Circle(object): def __init__(self, radius): self.radius = radius @property def area(self): return 3.14 * self.radius ** 2 c = Circle(4) print c.radius print c.area
zeigt, dass der Bereich zwar als Methode definiert ist, nach dem Hinzufügen der @-Eigenschaft jedoch direkt auf c.area als Eigenschaft zugegriffen werden kann.
Jetzt kommt das Problem. Jedes Mal, wenn c.area aufgerufen wird, wird es nur einmal berechnet. Das ist die Eigenschaft der Faulheit.
class lazy(object): def __init__(self, func): self.func = func def __get__(self, instance, cls): val = self.func(instance) setattr(instance, self.func.__name__, val) return val class Circle(object): def __init__(self, radius): self.radius = radius @lazy def area(self): print 'evalute' return 3.14 * self.radius ** 2 c = Circle(4) print c.radius print c.area print c.area print c.area
Wie Sie sehen, wird „evalute“ nur einmal ausgegeben, daher sollten Sie den Mechanismus von @Lazy gut verstehen.
Hier verfügt die Lazy-Klasse über eine __get__-Methode, die darauf hinweist, dass es sich bei der ersten Ausführung von c.area aufgrund von Auftragsproblemen zunächst um eine Suche in Ç.__dict__ handelt wurde nicht gefunden, gehen Sie einfach zum Klassenraum, um ihn zu finden. Im Klassenkreis gibt es die Methode „area()“, also wird sie von __get__ abgefangen.
Rufen Sie in __get__ die Region()-Methode der Instanz auf, um das Ergebnis zu berechnen, und fügen Sie der Instanz dynamisch ein Attribut mit demselben Namen hinzu und weisen Sie ihr das Ergebnis zu, dh fügen Sie es zu Ç hinzu. __ dict__.
Wenn Sie c.area erneut ausführen, gehen Sie zuerst zu Ç.__ dict__, um es zu finden, da es zu diesem Zeitpunkt bereits existiert, sodass Sie nicht die Methode „area()“ und „__get__“ durchlaufen müssen.
Hinweise
Bitte beachten Sie folgende Code-Szenarien:
Code-Schnipsel 1:
class Parrot(object): def __init__(self): self._voltage = 100000 @property def voltage(self): """Get the current voltage.""" return self._voltage if __name__ == "__main__": # instance p = Parrot() # similarly invoke "getter" via @property print p.voltage # update, similarly invoke "setter" p.voltage = 12
Code-Schnipsel 2:
class Parrot: def __init__(self): self._voltage = 100000 @property def voltage(self): """Get the current voltage.""" return self._voltage if __name__ == "__main__": # instance p = Parrot() # similarly invoke "getter" via @property print p.voltage # update, similarly invoke "setter" p.voltage = 12
Code 1, der Unterschied zwischen 2 ist
Klasse Parrot (Objekt):
Führen Sie den Test unter Python2 separat aus
Fragment 1: Eine erwartete Fehlermeldung AttributeError: Unable to werden aufgefordert, die Eigenschaft festzulegen
Fragment 2: Korrekt ausführen
Siehe die Python2-Dokumentation, die ein schreibgeschütztes Attribut bereitstellt Es liegt auf der Hand, dass der Code in Fragment 2 zu einem Fehler beim Ausführen führt. In der Python2-Dokumentation finden wir die folgenden Informationen:
BIF:
property ([fget [, fset [ , fdel [, doc]]]])
Gibt die Attributeigenschaften der neuen Stilklasse zurück (von Object abgeleitete Klassen).
Es stellt sich heraus, dass unter Python2 das integrierte Typobjekt nicht die Standardbasisklasse ist. Wenn es beim Definieren der Klasse (Code-Snippet 2) keine klare Erklärung gibt, wird der von uns definierte Parrot (Code-Snippet 2) verwendet ) erbt kein Objekt
Die Objektklasse stellt lediglich die @property-Funktion bereit, die wir benötigen. Wir können die folgenden Informationen im Dokument finden:
Neue Stilklasse
Jede Klasse das erbt von object . Dazu gehören alle integrierten Typen wie list und dict. Nur Klassen neuen Stils können die neueren, generischen Funktionen von Python wie __slots__, Deskriptoren, Attribute und __getattribute__() verwenden.
Gleichzeitig können wir dies auch mit der folgenden Methode überprüfen
class A: pass >>type(A) <type 'classobj'>
class A(object): pass >>type(A) <type 'type'>
Aus dem zurückgegebenen
Um zu berücksichtigen Frage zur Kompatibilität der Python-Version Übergangszeit des Codes: Ich denke, dass Objekte beim Definieren von Klassendateien explizit definiert werden sollten.
Der endgültige Code wird wie folgt aussehen:
class Parrot(object): def __init__(self): self._voltage = 100000 @property def voltage(self): """Get the current voltage.""" return self._voltage @voltage.setter def voltage(self, new_value): self._voltage = new_value if __name__ == "__main__": # instance p = Parrot() # similarly invoke "getter" via @property print p.voltage # update, similarly invoke "setter" p.voltage = 12
Das obige ist der detaillierte Inhalt vonSchwierige Verwendung von @property decorator in Python (Codebeispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!