Python 的 super() 如何处理多重继承? [英] How does Python's super() work with multiple inheritance?

查看:23
本文介绍了Python 的 super() 如何处理多重继承?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 Python 面向对象编程还很陌生,但遇到了麻烦理解 super() 函数(新样式类),尤其是在涉及多重继承时.

例如,如果你有类似的东西:

class First(object):def __init__(self):打印第一个"第二类(对象):def __init__(self):打印第二个"第三类(第一,第二):def __init__(self):超级(第三,自我).__init__()打印就是这样"

我不明白的是:Third() 类会继承两个构造函数方法吗?如果是,那么哪个将使用 super() 运行,为什么?

如果你想运行另一个怎么办?我知道这与 Python 方法解析顺序有关(MRO).

解决方案

Guido 本人在他的博文 方法解析顺序(包括之前的两次尝试).

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

第三类(第一、第二):...

Python 将首先查看 First,如果 First 没有该属性,那么它会查看 Second.

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

例如,如果您有:

class First(object):def __init__(self):打印第一个"第二类(第一类):def __init__(self):打印第二个"第三类(第一类):def __init__(self):打印第三个"第四类(二、三):def __init__(self):super(第四,self).__init__()打印就是这样"

MRO 将是 [第四、第二、第三、第一].

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

模棱两可的 MRO 示例:

class First(object):def __init__(self):打印第一个"第二类(第一类):def __init__(self):打印第二个"第三类(第一,第二):def __init__(self):打印第三个"

Third 的 MRO 应该是 [First, Second] 还是 [Second, First]?没有明显的期望,Python 会报错:

TypeError:调用元类基类时出错无法为碱基创建一致的方法解析顺序 (MRO) Second, First

为什么上面的例子缺少 super() 调用?示例的重点是展示 MRO 的构建方式.它们用于打印first second hird" 或其他任何内容.您可以——当然也应该使用示例,添加 super() 调用,看看会发生什么,并更深入地了解 Python 的继承模型.但我的目标是保持简单并展示 MRO 是如何构建的.它是按照我的解释构建的:

<预><代码>>>>第四.__mro__(<class '__main__.Fourth'>,, ,<class '__main__.First'>,<输入对象">)

I'm pretty much new in Python object oriented programming and I have trouble understanding the super() function (new style classes) especially when it comes to multiple inheritance.

For example if you have something like:

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"

What I don't get is: will the Third() class inherit both constructor methods? If yes, then which one will be run with super() and why?

And what if you want to run the other one? I know it has something to do with Python method resolution order (MRO).

解决方案

This is detailed with a reasonable amount of detail by Guido himself in his blog post Method Resolution Order (including two earlier attempts).

In your example, Third() will call First.__init__. Python looks for each attribute in the class's parents as they are listed left to right. In this case, we are looking for __init__. So, if you define

class Third(First, Second):
    ...

Python will start by looking at First, and, if First doesn't have the attribute, then it will look at Second.

This situation becomes more complex when inheritance starts crossing paths (for example if First inherited from Second). Read the link above for more details, but, in a nutshell, Python will try to maintain the order in which each class appears on the inheritance list, starting with the child class itself.

So, for instance, if you had:

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"

the MRO would be [Fourth, Second, Third, First].

By the way: if Python cannot find a coherent method resolution order, it'll raise an exception, instead of falling back to behavior which might surprise the user.

Example of an ambiguous 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"

Should Third's MRO be [First, Second] or [Second, First]? There's no obvious expectation, and Python will raise an error:

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

Why do the examples above lack super() calls? The point of the examples is to show how the MRO is constructed. They are not intended to print "first second hird" or whatever. You can – and should, of course, play around with the example, add super() calls, see what happens, and gain a deeper understanding of Python's inheritance model. But my goal here is to keep it simple and show how the MRO is built. And it is built as I explained:

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

这篇关于Python 的 super() 如何处理多重继承?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆