Explication détaillée de l'utilisation des propriétés du décorateur Python

巴扎黑
Libérer: 2017-08-18 17:11:53
original
2260 Les gens l'ont consulté

Le décorateur @property peut transformer une méthode en propriété et l'appeler. Jetons un coup d'œil à l'analyse des compétences d'utilisation du décorateur @property par la magie noire

À quoi sert @property en surface ? Il semble qu'une méthode soit accessible en tant qu'attribut. Le code dans

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
Copier après la connexion

Vous pouvez voir que bien que la zone soit définie comme une méthode, mais après avoir ajouté @property. , vous pouvez accéder directement à c.area en tant que propriété.

Maintenant, le problème survient, chaque fois que c.area est appelé, il sera calculé une fois, ce qui est un gaspillage de CPU. Comment puis-je le calculer uniquement. once ? Quoi ? C'est la propriété lazy.

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
Copier après la connexion

Comme vous pouvez le voir, 'evalute' n'est affiché qu'une seule fois, et le mécanisme de @lazy doit être bien compris.

Ici , la classe paresseuse a La méthode __get__ indique qu'il s'agit d'un descripteur Lorsque c.area est exécuté pour la première fois, en raison de problèmes d'ordre, il est d'abord recherché dans c.__dict__. l'espace de classe. Dans la classe Circle, il y a la méthode Area(), elle est donc interceptée par __get__

Dans __get__, appelez la méthode Area() de l'instance pour calculer le résultat, et ajoutez dynamiquement un. attribuez le même nom à l'instance et attribuez-lui le résultat, c'est-à-dire ajoutez-le à Go to c.__dict__.

Lors de l'exécution de c.area, accédez d'abord à c.__dict__, car il a déjà existe en ce moment, vous ne passerez donc pas par la méthode Area() et __get__

Notes

Veuillez faire attention aux scénarios de code suivants :

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
Copier après la connexion

Extrait de code 2 :

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
Copier après la connexion

La différence entre les codes 1 et 2 est que

classe Parrot(objet) :

Sous python2, exécutez le test séparément

Fragment 1 : Une erreur attendue sera demandée Information AttributeError : impossible de définir l'attribut

Fragment 2 : Opération correcte

Reportez-vous au documentation python2, @property fournira une propriété prête à l'emploi, le code ci-dessus ne fournit pas le @voltage.setter correspondant, il va de soi que l'extrait de code 2 provoquera une erreur d'exécution. Dans le document python2, nous pouvons trouver le. informations suivantes :

BIF :

property([fget[, fset[, fdel[, doc]] ]])

Renvoyer un attribut de propriété pour les classes de nouveau style (classes qui dérivent de l'objet).

Il s'avère que sous python2, l'objet de type intégré n'est pas la classe de base par défaut s'il s'agit d'une classe définie, s'il n'y a pas d'explication claire (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 fournit simplement la fonction @property dont nous avons besoin. Dans le document, vous pouvez trouver les informations suivantes :

<🎜. >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__, les descripteurs, les propriétés et. __getattribute__().

En même temps, nous pouvons également vérifier via la méthode suivante

class A: 
  pass 
>>type(A) 
<type &#39;classobj&#39;>
Copier après la connexion
class A(object): 
  pass 
>>type(A) 
<type &#39;type&#39;>
Copier après la connexion
Retourné de , nous pouvons voir que est le type d'objet dont nous avons besoin (Python 3.0 utilise la classe d'objet comme classe de base par défaut, il renverra donc )

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 des fichiers de classe, l'objet doit être explicitement défini comme une bonne habitude

Enfin, le code le fera être la suivante :

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
Copier après la connexion
De plus,

@property a été ajouté en 2.6 et 3.0, et la 2.5 n'a pas cette fonction.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!