super()如何处理多重继承?例如,给定:

class First(object):
    def __init__(self):
        print "first"

class Second(object):
    def __init__(self):
        print "second"

class Third(First, Second):
    def __init__(self):
        super(Third, self).__init__()
        print "that's it"

Third的哪个父方法执行super()。__init__ refer to?我可以选择哪些运行吗?

我知道这与方法解析顺序(MRO)有关。


当前回答

这就是所谓的钻石问题,该页面有一个关于Python的条目,但简而言之,Python将从左到右调用超类的方法。

其他回答

你的代码和其他答案都是错误的。它们缺少前两个类中的super()调用,这是合作子类化工作所必需的。更好的是:

class First(object):
    def __init__(self):
        super(First, self).__init__()
        print("first")

class Second(object):
    def __init__(self):
        super(Second, self).__init__()
        print("second")

class Third(First, Second):
    def __init__(self):
        super(Third, self).__init__()
        print("third")

输出:

>>> Third()
second
first
third

super()调用在每一步都在MRO中查找下一个方法,这就是为什么First和Second也必须拥有它,否则执行将在Second.__init__()结束时停止。


如果在First和Second中没有super()调用,输出就会丢失Second:

>>> Third()
first
third

在学习python的过程中,我学到了一个叫做super()的东西,如果没有弄错的话,这是一个内置函数。调用super()函数可以帮助继承通过父节点和“兄弟节点”传递,并帮助你看得更清楚。我仍然是初学者,但我喜欢分享我在python2.7中使用这个super()的经验。

如果您已经阅读了本页中的注释,您将听说方法解析顺序(MRO),该方法是您编写的函数,MRO将使用深度优先的左至右方案来搜索和运行。你可以做更多的研究。

通过添加super()函数

super(First, self).__init__() #example for class First.

你可以用super()连接多个实例和“家族”,方法是添加其中的每个实例和每个人。它会执行这些方法,检查它们,确保你没有错过!然而,在之前或之后添加它们确实会有区别,你会知道你是否已经通过硬路练习学习了python。让乐趣开始吧!!

以下面的例子为例,你可以复制粘贴并试着运行它:

class First(object):
    def __init__(self):

        print("first")

class Second(First):
    def __init__(self):
        print("second (before)")
        super(Second, self).__init__()
        print("second (after)")

class Third(First):
    def __init__(self):
        print("third (before)")
        super(Third, self).__init__()
        print("third (after)")


class Fourth(First):
    def __init__(self):
        print("fourth (before)")
        super(Fourth, self).__init__()
        print("fourth (after)")


class Fifth(Second, Third, Fourth):
    def __init__(self):
        print("fifth (before)")
        super(Fifth, self).__init__()
        print("fifth (after)")

Fifth()

它是如何运行的?fifth()的实例如下所示。每一步从一个类到另一个类,其中添加了超函数。

1.) print("fifth (before)")
2.) super()>[Second, Third, Fourth] (Left to right)
3.) print("second (before)")
4.) super()> First (First is the Parent which inherit from object)

父母已经找到了,会继续到第三和第四!!

5.) print("third (before)")
6.) super()> First (Parent class)
7.) print ("Fourth (before)")
8.) super()> First (Parent class)

现在所有带有super()的类都已经被访问了!父类已经找到并执行,现在它继续在继承中解箱函数以完成代码。

9.) print("first") (Parent)
10.) print ("Fourth (after)") (Class Fourth un-box)
11.) print("third (after)") (Class Third un-box)
12.) print("second (after)") (Class Second un-box)
13.) print("fifth (after)") (Class Fifth un-box)
14.) Fifth() executed

以上方案的成果:

fifth (before)
second (before
third (before)
fourth (before)
first
fourth (after)
third (after)
second (after)
fifth (after)

对我来说,添加super()可以让我更清楚地看到python如何执行我的代码,并确保继承可以访问我想要的方法。

在这种情况下,你试图继承的每个类都有自己的init位置参数,只需调用每个类自己的init方法,如果试图继承多个对象,则不要使用super。

class A():
    def __init__(self, x):
        self.x = x

class B():
    def __init__(self, y, z):
        self.y = y
        self.z = z

class C(A, B):
    def __init__(self, x, y, z):
        A.__init__(self, x)
        B.__init__(self, y, z)

>>> c = C(1,2,3)
>>>c.x, c.y, c.z 
(1, 2, 3)

我知道这并没有直接回答super()问题,但我觉得它有足够的相关性来分享。

还有一种方法可以直接调用每个继承的类:


class First(object):
    def __init__(self):
        print '1'

class Second(object):
    def __init__(self):
        print '2'

class Third(First, Second):
    def __init__(self):
        Second.__init__(self)

请注意,如果你这样做,你将不得不手动调用每个,因为我很确定First的__init__()不会被调用。

在python 3.5+中,继承看起来是可预测的,对我来说非常好。 请看下面的代码:

class Base(object):
  def foo(self):
    print("    Base(): entering")
    print("    Base(): exiting")


class First(Base):
  def foo(self):
    print("   First(): entering Will call Second now")
    super().foo()
    print("   First(): exiting")


class Second(Base):
  def foo(self):
    print("  Second(): entering")
    super().foo()
    print("  Second(): exiting")


class Third(First, Second):
  def foo(self):
    print(" Third(): entering")
    super().foo()
    print(" Third(): exiting")


class Fourth(Third):
  def foo(self):
    print("Fourth(): entering")
    super().foo()
    print("Fourth(): exiting")

Fourth().foo()
print(Fourth.__mro__)

输出:

Fourth(): entering
 Third(): entering
   First(): entering Will call Second now
  Second(): entering
    Base(): entering
    Base(): exiting
  Second(): exiting
   First(): exiting
 Third(): exiting
Fourth(): exiting
(<class '__main__.Fourth'>, <class '__main__.Third'>, <class '__main__.First'>, <class '__main__.Second'>, <class '__main__.Base'>, <class 'object'>)

正如你所看到的,它对每个继承链调用foo一次,其顺序与继承链的顺序相同。你可以通过调用.mro来获得订单:

Fourth -> Third -> First -> Second -> Base ->对象