fundas
¿Cómo anulo el __getattr__
método de una clase sin romper el comportamiento predeterminado?
miguel williamson
Primordial __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
después __getattr__
sólo se llamará si foo
no tiene atributo llamado 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)
-
Bah, tu edición tiene lo mismo que estaba mostrando en mi respuesta, +1.
– Roger paté
8 de marzo de 2010 a las 23:51
-
Genial, a Python no parece gustarle llamar a los súper
__getattr__
— ¿Alguna idea de qué hacer? (AttributeError: 'super' object has no attribute '__getattr__'
)– gatoatigrado
11 de junio de 2013 a las 23:33
-
Sin ver su código, es difícil saberlo, pero parece que ninguna de sus superclases define obtener.
– Colin VH
11/04/2015 a las 16:00
-
Esto funciona con hasattr también porque: “Esto se implementa al llamar a getattr (objeto, nombre) y ver si genera una excepción o no”. docs.python.org/2/library/functions.html#hasattr
– ShaBANG
7 de marzo de 2018 a las 17:13
-
-1 esto lo hace modificar el comportamiento predeterminado. Ahora tienes un
AttributeError
sin el contexto del atributo en los argumentos de excepción.– Wim
26 de noviembre de 2018 a las 19:43
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
-
Gracias por esto. Solo quería asegurarme de que tenía el mensaje predeterminado correcto sin buscar en la fuente.
– Shawn Fumo
4 de noviembre de 2013 a las 17:48
-
Creo que
self.__class__.__name__
debe usarse en lugar deself.__class__
en caso de que la clase anule__repr__
–Michael Scott Asato Cuthbert
11/01/2016 a las 20:46
-
Esta es una respuesta mejor que la aceptada, pero sería bueno no tener que volver a escribir ese código y potencialmente perder los cambios anteriores en caso de que se modifique la redacción o se agregue contexto adicional al objeto de excepción en el futuro.
– Wim
26 de noviembre de 2018 a las 19:56
Para extender la respuesta de Michael, si desea mantener el comportamiento predeterminado usando __getattr__
puedes 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'
-
@fed.pavlo ¿estás seguro? tal vez mezclaste
__getattr__
y__getattribute__
?– José Luis
16 de septiembre de 2016 a las 7:41
-
culpa mía. Perdí la llamada a un método diferente del propio. ;(
– fed.pavlo
19 de septiembre de 2016 a las 10:18
-
De hecho, la respuesta de @Michael está incompleta sin esta respuesta
–Grijesh Chauhan
12 de abril de 2018 a las 8:10
-
¿No debería ser
return super().__getattribute__(name)
por si acaso también tienes un__getattribute__
método en esta clase.– pauleohare
25 de febrero a las 14:06
“Romper”, pide, no “cambiar”. Eso está bastante claro: los atributos “elegantes” no deben interferir con los atributos integrados y deben comportarse como ellos tanto como sea posible. La respuesta de Michael es correcta y útil.
– olooney
9 de marzo de 2010 a las 0:04