Объект 'super' не вызывает __getattr__

У меня есть один объект, завернутый в другой. "Обертка" получает доступ к атрибутам объекта "Обернутый" путем переопределения __getattr__, Это работает хорошо, пока мне не нужно переопределить атрибут в подклассе, а затем получить доступ к атрибуту из базового класса, используя super(),

Я все еще могу получить доступ к атрибуту непосредственно из __getattr__ но почему 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()

1 ответ

Решение

В соответствии с этим, super не допускает неявные вызовы таких функций, как __getattr__, Я не уверен, почему это реализовано таким образом (вероятно, есть веская причина, и все уже достаточно запутанно, поскольку супер-объект имеет __getattribute__ а также __get__ методы, как есть), но кажется, что все так, как есть.

Изменить: Этот пост, кажется, прояснить ситуацию немного. Похоже, что проблема заключается в дополнительном слое косвенного __getattribute__ игнорируется при неявном вызове функций. дела foo.x эквивалентно

foo.__getattr__(x)

(Предполагая, что нет __getattribute__ Метод определен, а х не в foo.__dict__) Однако это НЕ эквивалентно

foo.__getattribute__('__getattr__')(x)

Поскольку super возвращает прокси-объект, у него есть дополнительный уровень косвенности, который приводит к ошибкам.

PS The self.__dict__ проверьте в вашем __getattr__ Функция совершенно не нужна. __getattr__ вызывается, только если атрибут не существует в вашем файле. (Использование __getattribute__ если вы хотите, чтобы он всегда вызывался, но тогда вы должны быть очень осторожны, потому что даже что-то простое, как if name in self.__dict__ вызовет бесконечную рекурсию.

Другие вопросы по тегам