如何在使用多重继承时使用super初始化所有父项

时间:2013-10-14 17:13:26

标签: python

How does Python's super() work with multiple inheritance?

我正在查看上面的问题/答案,让自己真的很困惑

 53 class First(object):
 54     def __init__(self):
 55         print "first"
 56
 57 class Second(First):
 58     def __init__(self):
 59         super(Second, self).__init__()
 60         print "second"
 61
 62 class Third(First):
 63     def __init__(self):
 64         print "third"
 65
 66 class Fourth(Second, Third):
 67     def __init__(self):
 68         super(Fourth, self).__init__()
 69         print "thats it"
  
    

第四()
    第三
    第二
    多数民众赞成

  
 53 class First(object):
 54     def __init__(self):
 55         print "first"
 56
 57 class Second(First):
 58     def __init__(self):
 59         #super(Second, self).__init__()         <---- commented out
 60         print "second"
 61
 62 class Third(First):
 63     def __init__(self):
 64         print "third"
 65
 66 class Fourth(Second, Third):
 67     def __init__(self):
 68         super(Fourth, self).__init__()
 69         print "thats it"
  
    

第四()
    第二
    多数民众赞成

  

有人可以向我解释一下,为什么顶部打印件"third"和底部打印件没有?为什么会幕后发生什么?

我觉得在我看不到的场景背后会发生某种顺序/顺序。

- 第四。 mro

在第二期评论超级 (,,,,)

超级二 (,,,,)

2 个答案:

答案 0 :(得分:4)

super实际上并没有调用超类。它根据方法解决顺序(MRO)调用下一个方法。看起来您的示例类的MRO如下:

Fourth
Second
Third
First

也就是说,使用super中的Fourth可以获得Second上的方法。使用super中的Second可以获得Third上的方法。等

在第一个例子中:

  1. Fourth.__init__被召唤。
  2. Fourth.__init__通过Second.__init__致电super
  3. Second.__init__通过Third.__init__致电super
  4. Third.__init__打印“第三”
  5. Second.__init__打印“第二个”
  6. Fourth.__init__打印“就是这样”。
  7. 在第二个例子中:

    1. Fourth.__init__被召唤。
    2. Fourth.__init__通过Second.__init__致电super
    3. Second.__init__打印“第二个”
    4. Fourth.__init__打印“就是这样”。
    5. 所以,是的,更改super中的Second来电会改变Third上的内容是否被调用,即使Third不是Second的超类}。这确实令人困惑。我建议阅读"Python's Super is nifty, but you can't use it"。这就是我读到的解释,让上述内容对我有意义。

答案 1 :(得分:3)

MRO不是嵌套层次结构。它是一个遵循一组约束的平面列表,即每个类必须在它的基类之前,并且这些基类必须以子类声明中提到的相对于彼此的顺序存在。

通过打印Fourth.__mro__,我们可以看到示例中的MRO是:

(<class '__main__.Fourth'>, 
<class '__main__.Second'>, 
<class '__main__.Third'>, 
<class '__main__.First'>, 
<type 'object'>)

super的每次调用都将调用MRO中的下一个方法。您可以将super个调用的数量视为您将要下降的MRO中的零索引“深度”。

由于第一个代码段中有super两次调用,因此调用Second.__init__Third.__init__(此外,当然还要调用直接类'init方法)。同样,在第二个代码段中,您只需拨打一次super,这意味着只会调用Second.__init__