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()