python - example - El objeto ''super'' no llama a__getattr__
range python 3 (1)
De acuerdo con esto, super no permite llamadas implícitas de funciones "gancho" como __getattr__
. No estoy seguro de por qué se implementa de esta manera (probablemente hay una buena razón y las cosas ya son lo suficientemente confusas ya que el súper objeto tiene los __getattribute__
personalizados __getattribute__
y __get__
como están), pero parece que es así como están las cosas.
Edit: Esta publicación parece aclarar un poco las cosas. Parece que el problema es que la capa adicional de __getattribute__
indirecto causada por __getattribute__
se ignora cuando se __getattribute__
funciones implícitamente. Hacer foo.x
es equivalente a
foo.__getattr__(x)
(Suponiendo que no se __getattribute__
definido el método __getattribute__
y que x no esté en foo.__dict__
) Sin embargo, NO es equivalente a
foo.__getattribute__(''__getattr__'')(x)
Dado que super devuelve un objeto proxy, tiene una capa adicional de indirección que hace que las cosas fallen.
PD: el self.__dict__
comprobar en su función __getattr__
es completamente innecesario. __getattr__
solo se llama si el atributo no existe en su dict. (Use __getattribute__
si desea que siempre se llame, pero luego debe tener mucho cuidado, porque incluso algo simple como if name in self.__dict__
causará una recursión infinita.
Tengo un objeto envuelto dentro de otro. El "Wrapper" accede a los atributos del objeto "Wrapped" al reemplazar __getattr__
. Esto funciona bien hasta que necesito anular un atributo en una subclase y luego acceder al atributo desde la clase base usando super()
.
Todavía puedo acceder al atributo directamente desde __getattr__
pero ¿por qué no funciona super()
?
class Wrapped(object):
def __init__(self, value):
self.value = value
def hello_world(self):
print ''hello world'', self.value
class Wrapper(object):
def __init__(self, obj):
self.wrapped_obj = obj
def __getattr__(self, name):
if name in self.__dict__:
return getattr(self, name)
else:
return getattr(self.wrapped_obj, name)
class Subclass(Wrapper):
def __init__(self, obj):
super(Subclass, self).__init__(obj)
def hello_world(self):
# this works
func = super(Subclass, self).__getattr__(''hello_world'')()
# this doesn''t
super(Subclass, self).hello_world()
a = Wrapped(2)
b = Subclass(a)
b.hello_world()