A quoi sert @property ? En apparence, c'est pour accéder à une méthode en tant qu'attribut
Le code est le plus clair
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
<🎜. >
Vous pouvez voir que bien que la zone soit définie comme une méthode, après avoir ajouté @property, vous pouvez directement c.area et y accéder en tant que propriété.Maintenant, le problème vient, (pas la technologie des excavatrices. Laquelle est la meilleure ), chaque fois que c.area est appelé, il sera calculé une fois, ce qui est un gaspillage de CPU. Comment peut-il être calculé une seule fois ? C'est une propriété paresseuse.
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
<🎜. >
Comme vous pouvez le voir, 'evalute' n'est affiché qu'une seule fois. Si vous lisez mes articles de blog précédents, vous devriez avoir une bonne compréhension du mécanisme de @lazy
Ici, la classe paresseuse a un __get__. Méthode, expliquant C'est un descripteur. Lorsque c.area a été exécuté pour la première fois, en raison de problèmes d'ordre, il a d'abord été recherché dans c.__dict__. S'il n'a pas été trouvé, il a été recherché dans l'espace de classe. Circle, il existe une méthode Area(), donc c'était __get__ intercepte.Dans __get__, appelez la méthode Area() de l'instance pour calculer le résultat, et ajoutez dynamiquement un attribut du même nom à l'instance et attribuez le résultat, c'est-à-dire ajoutez-le à c.__dict__.
Lorsque vous exécutez à nouveau c.area, allez d'abord dans c.__dict__, car il existe déjà à ce moment, vous ne passerez donc pas par la zone() method et __get__.
Remarque
Extrait de code 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
Extrait de code 2 :
Code Python2.6class 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
La différence entre les codes 1 et 2 est-ce que
class Parrot(object):
est en python2 6 fois, exécutez les tests séparément
Fragment 1 : un message d'erreur attendu AttributeError : impossible de définir l'attribut sera invitéFragment 2 : Exécuter correctement
Reportez-vous au document python2.6, @property fournira une propriété prête uniquement. Le code ci-dessus ne fournit pas le @voltage.setter correspondant. dans le fragment 2 provoquera une erreur d'exécution. Dans le document python2.6, nous pouvons trouver les informations suivantes :
BIF :
property([fget[, fset[, fdel[, doc]]] ])Renvoyer un attribut de propriété pour les classes de nouveau style (classes qui dérivent d'un objet).
À l'origine sous python2.6, l'objet de type intégré n'est pas la classe de base par défaut. lors de la définition de la classe (extrait de code 2), le Parrot que nous définissons (extrait de code 2) n'héritera pas de l'objet
et la classe d'objet fournira simplement la fonction @property dont nous avons besoin. dans le document :
classe de nouveau style
Toute classe qui hérite d'un objet. Cela inclut tous les types intégrés comme list et dict . Seules les classes de nouveau style peuvent utiliser les fonctionnalités les plus récentes et polyvalentes de Python telles que __slots__. , descripteurs, propriétés et __getattribute__().
En même temps, nous pouvons également vérifier via les méthodes suivantes
class A: pass >>type(A) <type 'classobj'>
Code Python 2.6
class A(object): pass >>type(A) <type 'type'>
renvoyé par Afin de prendre en compte les problèmes de compatibilité pendant la période de transition de la version python du code, je pense que lors de la définition du fichier de classe, l'objet doit être explicitement défini comme une bonne habitude Final Le code sera le suivant : De plus, @property a été ajouté en 2.6 et 3.0, et la 2.5 n'a pas cette fonctionnalité. Pour plus de conseils de décoration Python sur la magie noire @property et d'articles connexes, veuillez faire attention au site Web PHP chinois ! 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