Множественное наследование и вызов super()
Я получаю сообщение об ошибке: TypeError: __init__() принимает ровно 2 аргумента (дано 3)
При попытке создать экземпляр объекта из класса Top:
super (Middle1, self).__ init __ (name, "middle")
class Base(object):
def __init__(self, name, type):
pass
class Middle1(Base):
def __init__(self, name):
super(Middle1, self).__init__(name, "middle1")
class Middle2(Base):
def __init__(self, name):
super(Middle2, self).__init__(name, "middle2")
class Middle3(Base):
def __init__(self, name):
super(Middle3, self).__init__(name, "middle3")
class Top(Middle1, Middle2, Middle3):
def __init__(self):
super(Top, self).__init__("top")
# Here is where it produces the error
if __name__ == '__main__':
Top()
Что я не понимаю в этой проблеме множественного наследования?
Примечание: это Python 2.7
РЕДАКТИРОВАТЬ
Итак, я попробовал кое-что, что я думаю, работает для моего случая. Это равносильный конечный результат, я думаю, что он в первую очередь форсирует глубину, не вызывая super и вызывая каждый отдельный __init__ вместо этого.
class Base(object):
def __init__(self, name, type):
pass
class Middle1(Base):
def __init__(self, name, type = "middle1"):
super(Middle1, self).__init__(name, type)
class Middle2(Base):
def __init__(self, name, type = "middle2"):
super(Middle2, self).__init__(name, type)
class Middle3(Base):
def __init__(self, name, type = "middle3"):
super(Middle3, self).__init__(name, type)
class Top(Middle1, Middle2, Middle3):
def __init__(self):
Middle1.__init__(self, "top")
Middle2.__init__(self, "top")
Middle3.__init__(self, "top")
# No errors anymore
if __name__ == '__main__':
Top()
2 ответа
Во-первых, вы должны посмотреть на порядок разрешения метода Top
:
>>> for c in Top.__mro__: print c
...
<class '__main__.Top'>
<class '__main__.Middle1'>
<class '__main__.Middle2'>
<class '__main__.Middle3'>
<class '__main__.Base'>
<type 'object'>
Это поможет вам увидеть, к какому классу относится каждый звонок super
представляет собой.
Ваша ошибка в том, что вы считаете super(Middle1, self)
относится к (только) базовому классу Base
из Middle1
, Это не так: это относится к классу, следующему Middle1
в MRO self.__class__
, поскольку self.__class__
является Top
следующий класс в строке Middle2
, чья __init__
принимает только один аргумент
Использовать super
правильно из метода вы должны убедиться, что метод принимает одинаковые аргументы в каждом классе, потому что вы не можете предсказать, какой метод класса будет вызван, посмотрев на сам код; это полностью зависит от типа объекта, который инициирует цепочку вызовов, который может быть классом, о котором вы даже не знаете.
Есть два поста, которые я предлагаю прочитать:
- Супер () Python считается супер!
- Super Python изящен, но вы не можете использовать его очень осторожно, чтобы понять семантику
super
,
Вместе они дают вам хорошее понимание того, когда super
можно правильно использовать и как избежать проблемы, которую вы видите здесь.
(В полном раскрытии я недавно не читал ни одного поста, поэтому воздержусь от попыток обобщить рекомендации, представленные в каждом.)
Как именно вы создаете экземпляры Top объектов?
Учитывая ваш код выше, следующее работает нормально:
topObj = Top()
middleObj = Middle("middle")
baseObj = Base("base", "type")