Comprendre la différence entre __getattr__ et __ _ _ getattribute__
Je suis en train d'essayer de comprendre la différence entre __getattr__
et __getattribute__
, cependant, je suis en situation d'échec il.
La réponse pour le Dépassement de Pile question Différence entre __getattr__
et __getattribute__
dit:
__getattribute__
est invoquée avant de regarder les attributs réels sur
l'objet, et donc peut être difficile de
mettre en œuvre correctement. Vous pouvez vous retrouver dans
infini récurrences très facilement.
Je n'ai absolument aucune idée de ce que cela signifie.
Puis il va dire:
Vous voudrez certainement
__getattr__
.
Pourquoi?
J'ai lu que si __getattribute__
échoue, __getattr__
est appelé. Alors pourquoi il y a deux manières différentes de faire la même chose? Si mon code met en œuvre les nouvelles classes de style, que dois-je utiliser?
Je suis à la recherche pour des exemples de code pour claire à cette question. J'ai Googlé pour faire de mon mieux, mais les réponses que j'ai trouvé n'est pas de discuter du problème de fond.
Si il n'y a aucune documentation, je suis prêt à le lire.
- si elle permet, à partir de la documentation "afin d'éviter une récursion infinie dans cette méthode, sa mise en œuvre devrait toujours faire appel à la méthode de classe de base avec le même nom pour accéder à tous les attributs dont il a besoin, par exemple, l'objet.__getattribute__(self, nom)." [docs.python.org/2/reference/...
Vous devez vous connecter pour publier un commentaire.
Quelques bases en premier.
Avec des objets, vous devez faire face à ses attributs. Ordinairement, nous ne
instance.attribute
. Parfois, nous avons besoin de plus de contrôle (lorsque nous ne savons pas le nom de l'attribut à l'avance).Par exemple,
instance.attribute
deviendraitgetattr(instance, attribute_name)
. À l'aide de ce modèle, on peut récupérer l'attribut en fournissant le attribute_name comme une chaîne de caractères.Utilisation de
__getattr__
Vous pouvez aussi dire à une classe de la façon de traiter avec des attributs dont il n'a pas explicitement le gérer et de le faire via
__getattr__
méthode.Python appeler cette méthode à chaque fois que vous demandez un attribut qui n'a pas déjà été définies, de sorte que vous pouvez définir de quoi faire avec elle.
Un classique de cas d'utilisation:
Mises en garde et de l'utilisation de
__getattribute__
Si vous devez prendre chaque attribut indépendamment de savoir si il existe ou pas, utilisez
__getattribute__
à la place. La différence est que__getattr__
seulement est appelée pour les attributs qui n'existe pas réellement. Si vous définissez un attribut directement référence à cet attribut va le récupérer sans appel__getattr__
.__getattribute__
est appelée de tous les temps.getattr(instance, attribute_name)
. ". Ne devrait-elle pas être__getattribute__(instance, attribute_name)
?getattr(foo, 'bar')
est équivalent àfoo.bar
.__getattribute__
est appelé à chaque fois qu'un attribut d'accès se produit.Ce sera la cause d'une récursion infinie. Le coupable est ici la ligne
return self.__dict__[attr]
. Imaginons (C'est assez proche de la vérité) que tous les attributs sont stockés dansself.__dict__
et disponibles par leur nom. La lignetente d'accéder à la
a
attribut def
. Cela appellef.__getattribute__('a')
.__getattribute__
puis essaie de chargerself.__dict__
.__dict__
est un attribut deself == f
et ainsi de python appelsf.__getattribute__('__dict__')
qui tente à nouveau d'accéder à l'attribut'__dict__
'. C'est une récursion infinie.Si
__getattr__
avait été utilisé à la place puisf
a una
attribut.f.b
), alors il n'aurait pas été appelé à trouver__dict__
parce qu'il est déjà là et__getattr__
n'est invoquée que si toutes les autres méthodes de trouver l'attribut ont échoué.La "bonne" façon d'écrire la classe ci-dessus à l'aide de
__getattribute__
estsuper(Foo, self).__getattribute__(attr)
lie la__getattribute__
méthode du "plus proche" de la superclasse (officiellement, la prochaine classe dans la classe de la Méthode de Résolution de l'Ordre, ou MRO) à l'objet en coursself
et puis l'appelle et permet que de faire le travail.Tous de ce problème est évité par l'utilisation de
__getattr__
qui permet de Python le fais, c'est chose normale jusqu'à ce qu'un attribut n'est pas trouvé. À ce point, Python mains le contrôle de votre__getattr__
méthode et permet de venir avec quelque chose.Il est également intéressant de noter que vous pouvez exécuter dans une récursion infinie avec
__getattr__
.Je vais laisser ça comme un exercice.
Je pense que les autres réponses ont fait du bon travail en expliquant la différence entre
__getattr__
et__getattribute__
, mais une chose qui pourrait ne pas être clair, c'est pourquoi vous pouvez utiliser__getattribute__
. La chose cool à propos de__getattribute__
essentiellement vous permet de surcharge de la dot lors de l'accès à une classe. Cela vous permet de personnaliser la façon dont les attributs sont accessibles à un niveau faible. Par exemple, supposons que je veux définir une classe où toutes les méthodes qui ne font qu'une auto argument sont traités comme des propriétés:Et de l'interactif interprète:
Bien sûr c'est un exemple stupide et vous ne serait probablement pas besoin de cela, mais il vous montre la puissance que vous pouvez obtenir à partir d'primordial
__getattribute__
.