Quiero anular el __getattr__
método en una clase para hacer algo elegante, pero no quiero romper el comportamiento predeterminado.
¿Cuál es la forma correcta de hacer esto?
Quiero anular el __getattr__
método en una clase para hacer algo elegante, pero no quiero romper el comportamiento predeterminado.
¿Cuál es la forma correcta de hacer esto?
Respuestas:
La anulación __getattr__
debería estar bien: __getattr__
solo se llama como último recurso, es decir, si no hay atributos en la instancia que coincidan con el nombre. Por ejemplo, si accede foo.bar
, __getattr__
solo se llamará si foo
no se ha llamado ningún atributo bar
. Si el atributo es uno que no desea manejar, aumente AttributeError
:
class Foo(object):
def __getattr__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
raise AttributeError
Sin embargo, a diferencia de __getattr__
, __getattribute__
se llamará primero (solo funciona para nuevas clases de estilo, es decir, aquellas que heredan del objeto). En este caso, puede conservar el comportamiento predeterminado de la siguiente manera:
class Foo(object):
def __getattribute__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
return object.__getattribute__(self, name)
__getattr__
¿alguna idea de qué hacer? ( AttributeError: 'super' object has no attribute '__getattr__'
)
AttributeError
sin el contexto del atributo en los argumentos de excepción.
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__
debería usarse en lugar de self.__class__
en caso de que la clase se anule__repr__
Para ampliar la respuesta de Michael, si desea mantener el comportamiento predeterminado utilizando __getattr__
, puede hacerlo así:
class Foo(object):
def __getattr__(self, name):
if name == 'something':
return 42
# Default behaviour
return self.__getattribute__(name)
Ahora el mensaje de excepción es más descriptivo:
>>> 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__
y __getattribute__
?