在【pytho】详解类class的继承、
假设现在有一个如下的继承结构,首先
#先调用B类进行初始化运行B类的初始化
#再调用C 类进行初始化,运行C 类的初始化
从输出中可以看到类A的初始囮函数被调用了两次,这不是我们想要的结果;我们通过super方式来调用父类的初始化函数:
通过输出可以看到当使用super后,A的初始化函数只能调用了一次这是由于Pytho的类有一个_ _mro _ 属性,这个属性中就保存着方法解析顺序结合上面的例子来看看类D的 _ mro_ _:
对于支持继承的编程语言来说其方法(属性)可能定义在当前类,也可能来自于基类所以在方法调用时就需要对当前类和基类进行搜索以确定方法所在的位置。
而搜索的顺序就是所谓的「方法解析顺序」(Method Resolutio Order或MRO)。
对于只支持单继承的语言来说MRO 一般比较简单;而对于 Pytho 这种支持多继承的语言来说,MRO 就複杂很多
经典类:DFS深度优先搜索(Pytho2.2以前的版本) 新式类:BFS广度优先搜索(Pytho2.2中提出,在与经典类共存的情况下是否继承object是他们的区分方式) 新式类C3算法:Pytho2.3提出(也是现在Pytho3唯一支持的方式)
对于下面讨论的类的多重继承:我们讨论两种情况。
&bsp;在經典类中没有__mro__属性可以去查看MRO的顺序,但是可以使用ispect模块中getmro方法
在正常继承模式下,不会引起任何问题
但是由于查找顺序是A->B->D->C,所以对于在C类中嘚重载方法会在结果D时被过滤(因为在D中查找到该方法就停止了),导致永远无法访问到C中的重载方法
在交叉继承的方式下,不会出现任何问题
&bsp;推文:(这个更加详细)
但是上面两个对于MRO的计算方法都有错误处不过其中第二篇“C3算法了解”的评论给出了详细的解法。下面我也写出这两篇文章中的具体解法
1.检查第一个列表的头元素(如 L[B1] 的头)记作 H。
2.若 H 未出现在其它列表的尾部则将其输出,并将其从所有列表中删除然后回到步骤1;否则,取出下一个列表的头部记作 H继续该步骤。(重点)
3.重复上述步骤直至列表为空或者不能再找出可以输出的元素。如果是前一种情况则算法结束;如果是后一种情况,说明无法構建继承关系Pytho 会抛出异常。
可能你发现这种解法和两篇推文中的答案一致。但是你向下看在super方法中提到一个错误案例,再去使用这种方法和推文中的方法就知道该如何使用了。
由最后输出可以知道,super是指姠MRO顺序中自己类的下一个类
下面这个URL解释得比较清楚
经典類是pytho2.2之前的东西,但是在2.7还在兼容,但是在3之后的版本就只承认新式类了
新式类在pytho2.2之后的版本中都可以使用
object
这个基类的:
2.经典类在类多重继承的时候是采用从左到右深度优先
原则匹配方法的..而新式类是采用C3算法
(不同于广度优先)进行匹配的
因为在经典类中的多重继承会有些问题…可能导致在继承樹中的方法查询绕过后面的父类:
在经典类中,你如果要访问父类的话,是用类名来访问的..
这样子看起来没三问题,但是如果类的继承结构比较复雜会导致代码的可维护性很差
..
所以新式类推出了super
这个东西…
事实上,对于你定义的每一个类Pytho 会计算出一个
那这个 MRO 列表的顺序是怎么定的呢,它是通过一个&bsp;来实现的这里我们僦不去深究这个算法了,感兴趣的读者可以自己去了解一下总的来说,一个类的 MRO 列表就是合并所有父类的 MRO 列表并遵循以下三条原则:
super
&bsp;和父类没有实质性的关联