У меня есть цепочка наследования из трех классов: Baz наследует от Bar, наследует от Foo.Я хотел бы определить метод в классе Foo, который при вызове в подклассе возвращает выходные данные своего родительского класса, к которому добавлены собственные элементы.Это желаемый результат:
>>> foo = Foo()
>>> bar = Bar()
>>> baz = Baz()
>>> print foo.get_defining_fields()
['in Foo']
>>> print bar.get_defining_fields()
['in Foo', 'in Bar']
>>> print baz.get_defining_fields()
['in Foo', 'in Bar', 'in Baz']
Проблема в том, что я неправильно понимаю что-то об использовании super()
в методах суперкласса, вызываемых подклассами, или некоторых других деталях подкласса.Этот бит работает нормально:
>>> print foo.get_defining_fields()
['in Foo']
Но bar.get_defining_fields()
создает бесконечный цикл, который запускается сам до тех пор, пока RuntimeError
не будет поднят вместо вызова foo.get_defining_fields
и остановится там, как я хочу.
Вот код.
class Foo(object):
def _defining_fields(self):
return ['in Foo']
def get_defining_fields(self):
if self.__class__ == Foo:
# Top of the chain, don't call super()
return self._defining_fields()
return super(self.__class__, self).get_defining_fields() + self._defining_fields()
class Bar(Foo):
def _defining_fields(self):
return ['in Bar']
class Baz(Bar):
def _defining_fields(self):
return ['in Baz']
Итак, get_defining_fields
определен в суперклассе, и вызов super()
внутри него использует self.__class__
в попытке передать правильное имя подклассавызов в каждом подклассе.При вызове в Bar он разрешается до super(Bar, self).get_defining_fields()
, так что список, возвращаемый foo.get_defining_fields()
, будет добавлен к списку, возвращенному far.get_defining_fields()
.
Вероятно, простая ошибка, если вы правильно понимаете механику наследования Python ивнутреннюю работу super()
, но так как я, очевидно, нет, я был бы признателен, если бы кто-то мог указать мне на правильный способ сделать это.
РЕДАКТИРОВАТЬ : согласно ответу Даниэля Роземана, я попытался заменить вызов super()
на эту форму: return super(Foo, self).get_defining_fields() + self._defining_fields()
Теперь бесконечная рекурсия больше не происходит, но я получаю другую ошибку при вызове bar.get_defining_fields()
:
AttributeError: 'super' object has no attribute 'get_defining_fields'
Что-то еще все еще не в порядке.
РЕДАКТИРОВАТЬ : да, наконец-то разобрался, чего мне здесь не хватает.Отмеченный обновленный ответ Даниэля как принятый.