Heim  >  Artikel  >  Backend-Entwicklung  >  Analyse der Verwendungsfähigkeiten von Python Black Magic @Property Decorator

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

高洛峰
高洛峰Original
2017-01-23 14:50:321195Durchsuche

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 &#39;classobj&#39;>

Python 2.6-Code

class A(object):
  pass
 
>>type(A)
<type &#39;type&#39;>

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!

Stellungnahme:
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