Je veux remplacer la __getattr__
méthode sur une classe pour faire quelque chose de sophistiqué, mais je ne veux pas casser le comportement par défaut.
Quelle est la bonne façon de procéder?
Je veux remplacer la __getattr__
méthode sur une classe pour faire quelque chose de sophistiqué, mais je ne veux pas casser le comportement par défaut.
Quelle est la bonne façon de procéder?
Réponses:
Le remplacement __getattr__
devrait être bien - __getattr__
n'est appelé qu'en dernier recours, c'est-à-dire s'il n'y a pas d'attributs dans l'instance qui correspondent au nom. Par exemple, si vous accédez foo.bar
, alors __getattr__
ne sera appelé que si foo
aucun attribut n'est 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 de l'objet). Dans ce cas, vous pouvez conserver le comportement par défaut comme ceci:
class Foo(object):
def __getattribute__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
return object.__getattribute__(self, name)
Consultez la documentation Python pour en savoir plus .
__getattr__
- des idées quoi faire? ( AttributeError: 'super' object has no attribute '__getattr__'
)
AttributeError
sans le contexte de l'attribut dans les arguments d'exception.
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
self.__class__.__name__
devrait être utilisé au self.__class__
cas où la classe remplacerait__repr__
Pour étendre la réponse de Michael, si vous souhaitez conserver le comportement par défaut en utilisant __getattr__
, vous pouvez le faire comme ceci:
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'
__getattr__
et __getattribute__
?