Comment puis-je remplacer l'option __getattr__
d'une classe sans casser le comportement par défaut ?
Bah, votre édition contient la même chose que ce que j'ai montré dans ma réponse, +1.
Comment puis-je remplacer l'option __getattr__
d'une classe sans casser le comportement par défaut ?
Surpassement __getattr__
devrait aller bien __getattr__
n'est appelé qu'en dernier recours, c'est-à-dire si aucun attribut de l'instance ne correspond au nom. Par exemple, si vous accédez à foo.bar
alors __getattr__
ne sera appelé que si foo
n'a pas d'attribut appelé bar
. Si l'attribut est un attribut que vous ne voulez pas gérer, levez AttributeError
:
class Foo(object):
def __getattr__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
raise AttributeError
Toutefois, à la différence des __getattr__
, __getattribute__
sera appelée en premier (cela ne fonctionne que pour les nouvelles classes de style, c'est-à-dire celles qui héritent de l'objet). Dans ce cas, vous pouvez conserver le comportement par défaut comme suit :
class Foo(object):
def __getattribute__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
return object.__getattribute__(self, name)
Cool, Python n'a pas l'air d'aimer appeler des super en __getattr__
-- Une idée de ce qu'il faut faire ? ( AttributeError: 'super' object has no attribute '__getattr__'
)
Sans voir votre code, c'est difficile à dire, mais il semble qu'aucune de vos superclasses ne définisse getattr .
class A(object):
def __init__(self):
self.a = 42
def __getattr__(self, attr):
if attr in ["b", "c"]:
return 42
raise AttributeError("%r object has no attribute %r" %
(self.__class__.__name__, attr))
>>> a = A()
>>> a.a
42
>>> a.b
42
>>> a.missing
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in __getattr__
AttributeError: 'A' object has no attribute 'missing'
>>> hasattr(a, "b")
True
>>> hasattr(a, "missing")
False
Pour compléter la réponse de Michael, si vous souhaitez conserver le comportement par défaut en utilisant la fonction __getattr__
vous pouvez procéder de la manière suivante :
class Foo(object):
def __getattr__(self, name):
if name == 'something':
return 42
# Default behaviour
return self.__getattribute__(name)
Le message d'exception est désormais plus descriptif :
>>> foo.something
42
>>> foo.error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __getattr__
AttributeError: 'Foo' object has no attribute 'error'
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
20 votes
On demande "rupture", et non "changement". C'est suffisamment clair : les attributs "fantaisie" ne doivent pas interférer avec les attributs intégrés et doivent se comporter autant que possible comme eux. La réponse de Michael est à la fois correcte et utile.