Analyse der Verwendungsfähigkeiten von Python Black Magic @Property Decorator

高洛峰
Freigeben: 2017-01-23 14:50:32
Original
1187 Leute haben es durchsucht

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
Nach dem Login kopieren

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
Nach dem Login kopieren

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
Nach dem Login kopieren

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
Nach dem Login kopieren

Der Unterschied zwischen Code 1 und 2 ist, dass

class Parrot(object):
Nach dem Login kopieren

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 &#39;classobj&#39;>
Nach dem Login kopieren

Python 2.6-Code

class A(object):
  pass
 
>>type(A)
<type &#39;type&#39;>
Nach dem Login kopieren

zurückgegeben von , Es ist ersichtlich, dass der Objekttyp ist, den wir benötigen (Python 3.0 verwendet die Objektklasse als Standardbasisklasse, sodass alle 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
Nach dem Login kopieren

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!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage