为什么这是一个模棱两可的MRO?

时间:2017-12-14 08:29:57

标签: python multiple-inheritance

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"

Source

为什么Python不能创建一致的MRO?在我看来它非常清楚:

  1. 首先搜索第三个方法中是否存在方法
  2. 在第二个中搜索第一个
  3. 中不存在方法

    但如果你尝试一下:

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

3 个答案:

答案 0 :(得分:10)

为了“一致”,MRO应该满足这些限制:

  1. 如果一个类继承自多个超类,那么它在超类列表中先前列出的那些应该在MRO中比它稍后列出的那些更早。
  2. MRO中的每个班级都应该在它的任何超类之前。
  3. 您提议的层次结构没有任何可能的顺序满足这些约束。因为第三个被定义为从第二个之前的第一个继承,所以第一个应该在MRO之前的第二个之前。但是因为Second继承自First,Second应该来自MRO的First。这种矛盾无法调和。

    您可以详细了解Python用于计算MRO的精确方法,称为C3 linearization algorithm

答案 1 :(得分:0)

如果我们应用C3线性化算法:

i)排在第一位。

ii)如果此头不在任何其他列表的尾部,则将其添加到C的线性化中,然后从合并中的列表中将其删除

iii)否则,请查看下一个列表的开头,如果它是一个好的标题,请考虑

iv)然后重复该操作,直到所有班级都被删除或不可能找到好头。

O:是对象类

L [First] =首O

L [Second] = Second + merge(L [First],First)

现在解决L [第二]

L [Second] = Second + merge(FirstO,First)

首先是列表FirstO中的头,并且在列表First中,所以它是一个好的头。

L [Second] =第二+第一+ merge(O)

O是列表中唯一的头,这是个好头

L [Second] =第二+第一+ O

L [Second] =第二个第一O

L [Third] =第三+ merge(L [First],L [Second],FirstSecond)

现在解决L [第三]

L [Third] =第三+合并(FirstO,SecondFirstO,FirstSecond)

L [Third] =第三名+不可能找到好头。

第一个是列表FirstO的头部,但它是列表SecondFirstO的尾巴,第二个是列表SecondFirstO的头部,但它是列表FirstSecond的尾巴,而O则是列表FirstO和SecondFirstO的尾巴,所以不可能找到好头。

答案 2 :(得分:0)

Python 内部认为在子类之前没有超类。

根据您的代码。在扫描或加载类之后,Python 认为方法解析必须是:

Third -> Second -> First

这里,FirstSecond的超类。

但是在执行时,在检查了Third之后,它遇到了First,它是Second的超类。

因此出现了类型错误。

class Third(First, Second): # Wrong
class Third(Second, First): # Correct