Python-Python的super()如何处理多重继承?

发布于 2021-02-02 23:24:00

我在使用Python进行面向对象的编程方面非常陌生,并且在理解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()一起运行,为什么?

而如果要运行另一个呢?我知道这与Python方法解析顺序(MRO)有关。

关注者
0
被浏览
214
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    Guido自己在他的博客文章Method Resolution Order(包括两次较早的尝试)中对此进行了合理的详细说明。

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

    
    class Third(First, Second):
        ...
    

    Python将首先查看First,如果First没有该属性,则它将查看Second。

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

    因此,例如,如果你有:

    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"
    

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

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

    编辑:我看到几个人争辩说上面的示例缺少super()调用,所以让我解释一下:这些示例的重点是说明MRO的构造方式。它们不打算打印“第一\第二\第三”或其他内容。你可以并且应该当然使用该示例,添加super()调用,看看会发生什么,并且对Python的继承模型有更深入的了解。但我的目标是保持简单,并说明MRO的构建方式。正如我所解释的那样:

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


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看