Python MRO(Method Resolution Order)方法解析顺序

来源:互联网 发布:java mysql jdbc 编辑:程序博客网 时间:2024/05/22 00:14

对于Python中多重继承不太清楚,所以看了下相关文章。

以下摘自http://www.cnblogs.com/yiranlaobaitu/p/3764422.html

如果一个派生类有多个直接基类,而这些直接基类又有一个共同的基类,则在最终的派生类中保留改间接共同基类数据成员的多份同名成员。
在一个类中保留间接共同基类的多份同名成员,这种现象是人们不希望出现的。C++提供虚基类(virtual base class)的方法,使得在继承间接共同基类时只保留一份成员。

C++在存在多个同名成员时,会报错,如

#include <iostream>using namespace std;class A{    public:    void method(){        cout<<"A"<<endl;    }};class B: public A{};class C{    public:    void method(){        cout<<"C"<<endl;    }};class D: public B, public C{};int main(){    D d;    d.method():}

或者

#include <iostream>using namespace std;class A{    public:    void method(){        cout<<"A"<<endl;    }};class B: public A{};class C: public A{};class D: public B, public C{};int main(){    D d;    d.method():}

编译就会报错

error: request for member 'method' is ambiguous

正确的写法应该是用virtual class

#include <iostream>using namespace std;class A{    public:    void method(){        cout<<"A"<<endl;    }};class B: virtual public A{};class C: virtual public A{};class D: public B, public C{};int main(){    D d;    d.method():}

和C++不同,Python在多重继承时中可以存在多个同名成员

class A:    def __init__(self):        print 'A'class B(A):    passclass C(A):    passclass D(B, C):    passd = D()

python中采用MRO来处理这种二义性问题。
MRO的起源可以参考这篇文章:http://python.jobbole.com/85685/
这里只总结了下结论

Python2.2以前的版本:经典类时代,深度优先搜索
Python2.2版本:经典类MRO为深度优先搜索,新式类MRO为BFS
Python2.3到Python2.7:经典类和新式类采用C3算法
MRO
Python3:只有新式类,算法依然是C3算法

那么,什么是C3算法呢?

用C1C2…CN来记录类[C1, C2, …, CN]
另C是从B1, B2, …, BN继承,我们需要计算C的linearization L[C],

L[C(B1,…BN)] = C + merge(L[B1]L[B2]…L[BN], B1…BN)

且L[object] = object

看官网上的公式没明白那个merge是什么,后来从上面的链接看到,其实就是拓扑排序!

假设继承关系如下:

class D(object):    passclass E(object):    passclass F(object):    passclass C(D, F):    passclass B(E, D):    passclass A(B, C):    passif __name__ == '__main__':    print A.__mro__

得到
这里写图片描述

在新式类中,可以用super()来调用继承过来的方法,但需要注意的是,super()并不是调用父类,而是调用的继承顺序的下一个类,super()的第一个参数也可以是继承链中的任意一个类。

原创粉丝点击