Heim > Artikel > Backend-Entwicklung > Analyse der Verwendungsfähigkeiten von Python Black Magic @Property Decorator
Was ist der Nutzen von @property? Oberflächlich betrachtet ist es der Zugriff auf eine Methode als Attribut
Der Code ist am klarsten
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
Sie können sehen, dass, obwohl der Bereich als Methode definiert ist, Sie nach dem Hinzufügen von @property direkt auf c.area zugreifen und als Eigenschaft darauf zugreifen können.
Jetzt kommt das Problem (nicht die Baggertechnologie). Welche ist besser? ), jedes Mal, wenn c.area aufgerufen wird, wird es einmal berechnet, was eine Verschwendung von CPU ist. Wie kann es nur einmal berechnet werden?
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 können, wird „evalute“ nur einmal ausgegeben. Wenn Sie meine vorherigen Blogbeiträge lesen, sollten Sie den Mechanismus von @lazy gut verstehen.
Hier hat die Lazy-Klasse einen __get__. Methode, erklären Es handelt sich um einen Deskriptor, der aufgrund von Auftragsproblemen zuerst in c.__dict__ gesucht wurde. Wenn er nicht gefunden wurde, wurde er im Klassenraum durchsucht Circle, es gibt eine Methode „area()“, daher wurden __get__-Abschnitte ausgeführt.
Rufen Sie in __get__ die Methode „area()“ der Instanz auf, um das Ergebnis zu berechnen, und fügen Sie der Instanz dynamisch ein Attribut mit demselben Namen hinzu und weisen Sie es zu Fügen Sie das Ergebnis hinzu, das heißt, fügen Sie es zu c.__dict__ hinzu.
Wenn Sie c.area erneut ausführen, gehen Sie zuerst zu c.__dict__, da es zu diesem Zeitpunkt bereits existiert, sodass Sie den Bereich nicht durchlaufen müssen () method und __get__.
Hinweis
Bitte beachten Sie die folgenden Codeszenarien:
Codeausschnitt 1:
Python2.6-Code
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
Codeausschnitt 2:
Python2.6-Code
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
Der Unterschied zwischen Code 1 und 2 ist, dass
class Parrot(object):
6 Mal in Python2 ist, führen Sie die Tests separat aus
Fragment 1: Eine erwartete Fehlermeldung AttributeError: can't set attribute wird angezeigt
Fragment 2: Korrekt ausführen
Beziehen Sie sich auf das Python2.6-Dokument. @property stellt eine schreibgeschützte Eigenschaft bereit. Es liegt auf der Hand, dass der Code den entsprechenden Code bereitstellt in Fragment 2 führt zu einem laufenden Fehler. Im Python2.6-Dokument finden wir die folgenden Informationen:
BIF:
property([fget[, fset[, fdel[, doc]]] ])
Gibt ein Eigenschaftsattribut für Klassen neuen Stils zurück (Klassen, die von Objekten abgeleitet sind).
Ursprünglich ist das integrierte Typobjekt nicht die Standardbasisklasse Beim Definieren der Klasse (Code-Snippet 2) erbt der von uns definierte Parrot (Code-Snippet 2) kein Objekt
und die Objektklasse stellt nur die @property-Funktion bereit, die wir benötigen. Wir können die folgenden Informationen finden im Dokument:
Klasse neuen Stils
Jede Klasse, die von Objekt erbt. Dazu gehören alle integrierten Typen wie list und dict. Nur Klassen neuen Stils können die neueren, vielseitigen Funktionen von Python verwenden. , Deskriptoren, Eigenschaften und __getattribute__().
Gleichzeitig können wir auch mit den folgenden Methoden überprüfen:
Python 2.6-Code
class A: pass >>type(A) <type 'classobj'>
Python 2.6-Code
class A(object): pass >>type(A) <type 'type'>
zurückgegeben von 4869e6839fe319857220e52bb96ddca9, f5ae6bbdf402bfea04a71faa8c02de77 Es ist ersichtlich, dass f5ae6bbdf402bfea04a71faa8c02de77 der Objekttyp ist, den wir benötigen (Python 3.0 verwendet die Objektklasse als Standardbasisklasse, sodass alle f5ae6bbdf402bfea04a71faa8c02de77 zurückgeben)
Um die Kompatibilitätsprobleme während der Übergangszeit der Python-Version des Codes zu berücksichtigen, denke ich, dass bei der Definition der Klassendatei das Objekt explizit als gute Angewohnheit definiert werden sollte
Final Der 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
Außerdem wurde @property in 2.6 und 3.0 hinzugefügt und 2.5 verfügt nicht über diese Funktion.
Weitere Tipps zum Dekorieren von Python Black Magic @property und verwandte Artikel finden Sie auf der chinesischen PHP-Website!