J'essaie de comprendre quand utiliser __getattr__
ou __getattribute__
. Le site documentation mentionne __getattribute__
s'applique aux classes de type nouveau. Qu'est-ce qu'une classe de type nouveau ?
Réponses
Trop de publicités?- obtenir l'attribut : Est utilisé pour récupérer un attribut d'une instance. Il capture chaque tentative d'accès à un attribut d'instance en utilisant la notation point ou la fonction intégrée getattr().
- getattr : Est exécuté comme dernière ressource lorsque l'attribut n'est pas trouvé dans un objet. Vous pouvez choisir de retourner une valeur par défaut ou de lever AttributeError.
Pour en revenir à la __getattribut__ si l'implémentation par défaut n'a pas été remplacée, les contrôles suivants sont effectués lors de l'exécution de la méthode :
- Vérifier s'il existe un descripteur portant le même nom (nom de l'attribut) défini dans une classe quelconque de la chaîne MRO (résolution d'objet de méthode).
- Ensuite, on regarde dans l'espace de nom de l'instance
- Ensuite, on regarde dans l'espace de nom de la classe
- Puis dans l'espace de noms de chaque base et ainsi de suite.
- Enfin, si elle n'est pas trouvée, l'implémentation par défaut appelle la méthode de repli (fallback) getattr () de l'instance et elle lève une exception AttributeError comme implémentation par défaut.
Il s'agit de l'actuel mise en œuvre de la méthode object.__getattribute__ :
. c:fonction: : PyObject* PyObject_GenericGetAttr(PyObject *o, PyObject *name) Fonction générique de récupération d'attribut qui est destinée à être placée dans le slot tp_getattro d'un objet de type. être placée dans le slot tp_getattro d'un objet de type. Elle recherche un descripteur dans le dictionnaire des classes dans le MRO de l'objet ainsi que ainsi qu'un attribut dans le :attr:~object de l'objet. dict (si présents). Comme indiqué dans :ref:descriptors, les descripteurs de données ont la préférence sur les attributs d'instance, tandis que les descripteurs non-données ne le font pas. Dans le cas contraire, une erreur :exc:AttributeError est générée.
En lisant le PCB de Beazley & Jones, je suis tombé sur un cas d'utilisation explicite et pratique de l'outil de gestion de l'information. __getattr__
qui aide à répondre à la partie "quand" de la question de l'OP. Dans le livre :
" Le __getattr__()
est en quelque sorte un fourre-tout pour la recherche d'attributs. C'est une méthode qui est appelée si le code tente d'accéder à un attribut qui n'existe pas." Nous le savons d'après les réponses ci-dessus, mais dans la recette PCB 8.15, cette fonctionnalité est utilisée pour implémenter la méthode modèle de conception de délégation . Si l'objet A possède un attribut objet B qui implémente de nombreuses méthodes que l'objet A veut déléguer, plutôt que de redéfinir toutes les méthodes de l'objet B dans l'objet A juste pour appeler les méthodes de l'objet B, définissez une méthode __getattr__()
comme suit :
def __getattr__(self, name):
return getattr(self._b, name)
où _b est le nom de l'attribut de l'objet A qui est un objet B. Lorsqu'une méthode définie sur l'objet B est appelée sur l'objet A, la fonction __getattr__
sera invoquée à la fin de la chaîne de recherche. Cela rendrait également le code plus propre, puisque vous n'avez pas une liste de méthodes définies juste pour déléguer à un autre objet.
Je trouve que personne ne mentionne cette différence :
__getattribute__
a une implémentation par défaut, mais __getattr__
ne le fait pas.
class A:
pass
a = A()
a.__getattr__ # error
a.__getattribute__ # return a method-wrapper
Cela a une signification claire : puisque __getattribute__
a une implémentation par défaut, tandis que __getattr__
non, il est clair que python encourage les utilisateurs à implémenter __getattr__
.
- Réponses précédentes
- Plus de réponses
2 votes
Duplicata possible de Comprendre la différence entre __getattr__ et __getattribute__
12 votes
@Trilarion pourtant cette question mentionne une réponse d'ici...