Der @property-Dekorator kann eine Methode in eine Eigenschaft umwandeln und sie aufrufen. Werfen wir einen Blick auf die Analyse der Verwendungsfähigkeiten des @property-Dekorators.
Was ist der Nutzen von @property? Es scheint, dass auf eine Methode als Attribut zugegriffen wird.
Sie können sehen, dass der Bereich zwar als Methode definiert ist, aber nach dem Hinzufügen von @property , Sie können direkt auf c.area als Eigenschaft zugreifen
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
Nach dem Login kopieren
Jetzt tritt das Problem auf, dass jedes Mal, wenn c.area aufgerufen wird, es einmal berechnet wird, was eine Verschwendung von CPU ist einmal? Was? Das ist die Lazy-Eigenschaft.
Wie Sie sehen können, wird „evalute“ nur einmal ausgegeben, und der Mechanismus von @lazy sollte gut verstanden 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
Nach dem Login kopieren
Hier Die Lazy-Klasse weist darauf hin, dass es sich bei der ersten Ausführung von c.area um einen Deskriptor handelt. Wenn dieser nicht gefunden wird, wird er aufgrund von Auftragsproblemen durchsucht Im Klassenraum gibt es die Methode „area( )“, also wird sie von __get__ abgefangen. Rufen Sie in __get__ die Methode „area()“ der Instanz auf und fügen Sie dynamisch eine hinzu Attribut mit demselben Namen zur Instanz und weisen Sie ihr das Ergebnis zu, das heißt, fügen Sie es zu Gehe zu c.__dict__ hinzu.
Wenn Sie c.area erneut ausführen, gehen Sie zuerst zu c.__dict__, da es bereits vorhanden ist existiert zu diesem Zeitpunkt, daher werden Sie die Methode „area()“ und __get__ nicht durchlaufen.
Hinweise
Bitte beachten Sie die folgenden Codeszenarien:
Codeausschnitt 1 :
Codeausschnitt 2:
Der Unterschied zwischen Code 1 und 2 besteht darin, dass
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
Nach dem Login kopieren
Klasse Parrot(object):
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
Nach dem Login kopieren
Führen Sie den Test unter Python2 separat aus
Fragment 1: Ein erwarteter Fehler wird angezeigt. Information AttributeError: Attribut kann nicht festgelegt werden
Fragment 2: Korrekter Vorgang
Siehe In der Python2-Dokumentation stellt @property eine schreibgeschützte Eigenschaft bereit. Der obige Code stellt den entsprechenden @length.setter nicht bereit. Es liegt auf der Hand, dass der Snippet-2-Code einen laufenden Fehler auslöst. Im Python2-Dokument können wir Folgendes finden Folgende Informationen:
BIF:
property([fget[, fset[, fdel[, doc]] ]])
Gibt ein Eigenschaftsattribut für Klassen neuen Stils zurück (Klassen, die von Objekt abgeleitet sind).
Es stellt sich heraus, dass unter Python2 der integrierte Typ Objekt nicht die Standardbasisklasse ist, wenn es keine klare Erklärung gibt (Codeausschnitt 2 ), erbt der von uns definierte Parrot (Codeausschnitt 2) kein Objekt
und die Objektklasse stellt nur die @property-Funktion bereit, die wir benötigen. Im Dokument finden Sie die folgenden Informationen:
Klasse im neuen Stil
Jede Klasse, die von Objekt erbt. Dazu gehören alle integrierten Typen wie Liste und Diktat. Nur Klassen im neuen Stil können die neueren, vielseitigen Funktionen von Python wie __slots__, Deskriptoren und Eigenschaften verwenden __getattribute__().
Gleichzeitig können wir auch mit der folgenden Methode überprüfen
Zurückgegeben von
, können wir sehen, dass der Objekttyp ist, den wir benötigen (Python 3.0 verwendet die Objektklasse als Standardbasisklasse, daher wird zurückgegeben)Um die Kompatibilitätsprobleme während der Übergangsphase der Python-Version des Codes zu berücksichtigen, denke ich, dass bei der Definition von Klassendateien das Objekt explizit als gute Angewohnheit definiert werden sollteclass A:
pass
>>type(A)
<type 'classobj'>
Nach dem Login kopieren
class A(object):
pass
>>type(A)
<type 'type'>
Nach dem Login kopieren
Schließlich wird der Code wie folgt sein:
Außerdem wurde
@property in 2.6 und 3.0 hinzugefügt, und 2.5 verfügt nicht über diese Funktion. Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Eigenschaftsverwendung des Python-Dekorators. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!