Je veux remplacer le __getattr__
méthode sur une classe pour faire quelque chose de chic mais je ne veux pas casser le comportement par défaut.
Quelle est la bonne façon de faire cela?
Remplacement __getattr__
devrait être bon - __getattr__
n'est appelé qu'en dernier recours, c'est-à-dire s'il n'y a pas d'attribut dans l'instance correspondant au nom. Par exemple, si vous accédez à foo.bar
, puis __getattr__
ne sera appelé que si foo
ne possède aucun attribut appelé bar
. Si l'attribut est un attribut que vous ne souhaitez pas gérer, augmentez AttributeError
:
class Foo(object):
def __getattr__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
raise AttributeError
Cependant, contrairement à __getattr__
, __getattribute__
sera appelé en premier (ne fonctionne que pour les nouvelles classes de style, c’est-à-dire celles qui héritent d’un 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)
Voir the Python docs pour plus) .
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 étendre la réponse à Michael, si vous souhaitez conserver le comportement par défaut à l'aide de __getattr__
, tu peux le faire comme ça:
class Foo(object):
def __getattr__(self, name):
if name == 'something':
return 42
# Default behaviour
return self.__getattribute__(name)
Maintenant, le message d'exception est 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'