Multiple Inheritance and calling super()

I get the error: TypeError: __init__() takes exactly 2 arguments (3 given)

When trying to instantiate an object from the class 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()

What am I not understanding about this multiple inheritance issue?

Note: this is python 2.7

EDIT

Ok so I tried something that I think works for my case. This is the equivelent end result, I think it's basically forcing depth first by not calling super and calling each individual __init__ instead.

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

First, you have to look at the method resolution order of 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'>

This helps you see which class each call to super represents.

Your mistake is thinking that the call to super(Middle1, self) refers to the (only) base class Base of Middle1 . It does not: it refers to the the class following Middle1 in the MRO of self.__class__ . Since self.__class__ is Top , the next class in line is Middle2 , whose __init__ takes only one argument.

To use super correctly from a method, you need to ensure that the method takes the same arguments in every class, because you cannot predict which class's method will be called by looking at the code itself; it depends entirely on the type of the object that initiates the chain of calls, which might be a class you aren't even aware of yet.

There are two posts I suggest reading:

  • Python's super() considered super!
  • Python's Super is nifty, but you can't use it very carefully to understand the semantics of super .
  • Together, they give you a good understanding of when super can be used correctly and how to avoid the problem you see here.

    (In full disclosure, I haven't read either post recently, so I will refrain from trying to summarize the advice presented in each.)


    How exactly are you instantiating Top objects?

    Given your code above, the following works fine:

       topObj = Top()
       middleObj = Middle("middle")
       baseObj = Base("base", "type")
    
    链接地址: http://www.djcxy.com/p/26788.html

    上一篇: 实时时间序列数据中的峰值信号检测

    下一篇: 多重继承和调用super()