Python的super()如何与多重继承一起工作?

2022-09-05 01:02:03

如何使用多重继承?例如,给定: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"

哪个父方法可以指?我可以选择哪些运行吗?Thirdsuper().__init__

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


答案 1

Guido本人在他的博客文章“方法解决顺序”(包括之前的两次尝试)中对此进行了合理的详细介绍。

在您的示例中,将调用 。Python在类的父级中查找每个属性,因为它们从左到右列出。在这种情况下,我们正在寻找.因此,如果您定义Third()First.__init____init__

class Third(First, Second):
    ...

Python 将从 查看 开始,如果没有该属性,则它将查看 。FirstFirstSecond

当继承开始交叉路径(例如,如果继承自 )时,这种情况变得更加复杂。阅读上面的链接以获取更多详细信息,但是,简而言之,Python将尝试保持每个类在继承列表中出现的顺序,从子类本身开始。FirstSecond

因此,例如,如果您有:

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

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

class Third(First):
    def __init__(self):
        print "third"

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

MRO将是[Fourth, Second, Third, First].

顺便说一句:如果Python找不到一个连贯的方法解析顺序,它会引发一个异常,而不是回退到可能会让用户感到惊讶的行为。

不明确的 MRO 示例:

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

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

的 MRO 应该是 还是 ?没有明显的期望,Python会引发一个错误:Third[First, Second][Second, First]

TypeError: Error when calling the metaclass bases
    Cannot create a consistent method resolution order (MRO) for bases Second, First

为什么上面的例子缺少调用?这些示例的要点是展示 MRO 是如何构造的。它们不是为了打印或其他任何东西。当然,你可以——当然,应该尝试这个例子,添加调用,看看会发生什么,并更深入地了解Python的继承模型。但我在这里的目标是保持简单,并展示MRO是如何构建的。正如我所解释的那样,它是构建的:super()"first\nsecond\third"super()

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

答案 2

你的代码和其他答案都是错误的。它们缺少前两个类中的调用,这些调用是合作子类化工作所必需的。更好的是: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

该调用在每个步骤中查找 MRO 中的下一个方法,这就是原因,并且也必须拥有它,否则执行将在 结束时停止。super()FirstSecondSecond.__init__()


如果没有 和 中的调用,则缺少输出:super()FirstSecondsecond

>>> Third()
first
third