Je souhaite remplacer l'accès à une variable dans une classe, mais renvoyer toutes les autres normalement. Comment puis-je accomplir cela avec __getattribute__
?
J'ai essayé ce qui suit (qui devrait également illustrer ce que j'essaie de faire) mais j'obtiens une erreur de récursivité:
class D(object):
def __init__(self):
self.test=20
self.test2=21
def __getattribute__(self,name):
if name=='test':
return 0.
else:
return self.__dict__[name]
>>> print D().test
0.0
>>> print D().test2
...
RuntimeError: maximum recursion depth exceeded in cmp
super(D, self).__getattribute__(name)
super().__getattribute__(name)
en Python 3.En fait, je pense que vous souhaitez utiliser la
__getattr__
méthode spéciale à la place.Citation de la documentation Python:
Remarque: pour que cela fonctionne, l'instance ne doit pas avoir d'
test
attribut, la ligneself.test=20
doit donc être supprimée.la source
__getattr__
fortest
serait inutile, car il le trouverait toujours «aux endroits habituels».Référence du langage Python:
Sens:
Vous appelez pour un attribut appelé
__dict__
. Parce que c'est un attribut,__getattribute__
est appelé à la recherche de__dict__
quels appels__getattribute__
qui appelle ... yada yada yadaL'utilisation des classes de base
__getattribute__
aide à trouver l'attribut réel.la source
Êtes-vous sûr de vouloir l'utiliser
__getattribute__
? Qu'essayez-vous réellement d'accomplir?La façon la plus simple de faire ce que vous demandez est:
ou:
Modifier: Notez qu'une instance de
D
aurait des valeurs différentes detest
dans chaque cas. Dans le premier casd.test
, 20, dans le second, 0. Je vous laisse le soin de comprendre pourquoi.Edit2: Greg a souligné que l'exemple 2 échouera car la propriété est en lecture seule et la
__init__
méthode a essayé de la définir sur 20. Un exemple plus complet serait:De toute évidence, en tant que classe, cela est presque entièrement inutile, mais cela vous donne une idée de départ.
la source
Voici une version plus fiable:
Il appelle la méthode __ getattribute __ de la classe parente, pour finalement revenir à l'objet. __ méthode getattribute __ si les autres ancêtres ne la remplacent pas.
la source
Il est appelé avant la recherche pointillée normale. Si cela augmente
AttributeError
, alors nous suivons__getattr__
.L'utilisation de cette méthode est plutôt rare. Il n'y a que deux définitions dans la bibliothèque standard:
Meilleur entrainement
La méthode appropriée pour contrôler par programme l'accès à un seul attribut est d'utiliser
property
. La classeD
doit être écrite comme suit (avec le setter et le deleter en option pour reproduire le comportement prévu apparent):Et l'utilisation:
Une propriété est un descripteur de données, c'est donc la première chose recherchée dans l'algorithme de recherche en pointillé normal.
Options pour
__getattribute__
Vous avez plusieurs options si vous devez absolument implémenter la recherche pour chaque attribut via
__getattribute__
.AttributeError
, provoquant__getattr__
l'appel (si implémenté)super
pour appeler le parent (probablementobject
implémentation )__getattr__
Par exemple:
Ce que vous vouliez à l'origine.
Et cet exemple montre comment vous pourriez faire ce que vous vouliez à l'origine:
Et se comportera comme ceci:
Revue de code
Votre code avec des commentaires. Vous avez une recherche en pointillé sur vous-même
__getattribute__
. C'est pourquoi vous obtenez une erreur de récursivité. Vous pouvez vérifier si le nom est"__dict__"
et utilisersuper
pour contourner le problème, mais cela ne couvre pas__slots__
. Je vais laisser cela comme un exercice au lecteur.la source