简体   繁体   English

多重继承并调用super()

[英]Multiple Inheritance and calling super()

I get the error: TypeError: __init__() takes exactly 2 arguments (3 given) 我收到错误:TypeError:__init __()恰好接受2个参数(给定3个)

When trying to instantiate an object from the class Top: 尝试从类Top实例化对象时:

super(Middle1, self).__init__(name, "middle") 超级(中间1,自我)。__init __(名称,“中间”)

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 注意:这是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. 这是等价的最终结果,我认为基本上是通过不调用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()

First, you have to look at the method resolution order of Top : 首先,您必须查看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. 这可以帮助您查看每个对super调用代表的类。

Your mistake is thinking that the call to super(Middle1, self) refers to the (only) base class Base of Middle1 . 你的错误是认为调用super(Middle1, self)指(只)基类BaseMiddle1 It does not: it refers to the the class following Middle1 in the MRO of self.__class__ . 它不是:它引用self.__class__的MRO中Middle1之后的类。 Since self.__class__ is Top , the next class in line is Middle2 , whose __init__ takes only one argument. 由于self.__class__Top ,因此下一行是Middle2 ,其__init__仅接受一个参数。

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; 要正确地使用某个方法的super方法,您需要确保该方法在每个类中采用相同的参数,因为您无法通过查看代码本身来预测将调用哪个类的方法。 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: 我建议阅读两篇文章:

Together, they give you a good understanding of when super can be used correctly and how to avoid the problem you see here. 在一起,它们使您对何时可以正确使用super以及如何避免在此处看到的问题有一个很好的了解。

(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? 您究竟如何实例化Top对象?

Given your code above, the following works fine: 鉴于上面的代码,以下代码可以正常工作:

   topObj = Top()
   middleObj = Middle("middle")
   baseObj = Base("base", "type")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM