【问题标题】:Why is this an ambiguous MRO?为什么这是一个模棱两可的 MRO?
【发布时间】:2018-05-28 06:45:30
【问题描述】:
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. 如果方法在 First 中不存在,则在 Second 中搜索

但如果你尝试一下:

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

【问题讨论】:

标签: python multiple-inheritance


【解决方案1】:

要“一致”,MRO 应满足以下约束:

  1. 如果一个类继承自多个超类,则它在超类列表中较早列出的那些在 MRO 中应该比它在后面列出的更早。
  2. MRO 中的每个类都应位于其任何超类之前。

您建议的层次结构没有任何可能满足这些约束的顺序。因为 Third 被定义为在 Second 之前从 First 继承,所以在 MRO 中 First 应该在 Second 之前。但是因为 Second 继承自 First,所以在 MRO 中 Second 应该排在 First 之前。这种矛盾是无法调和的。

您可以阅读有关 Python 用于计算 MRO 的精确方法的更多信息,称为 C3 linearization algorithm

【讨论】:

【解决方案2】:

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

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

Third -> Second -> First

这里,FirstSecond的超类。

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

因此出现 TypeError。

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

【讨论】:

    【解决方案3】:

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

    i) 占据第一个列表的头部。

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

    iii) 否则看下一个列表的头部,如果是好的头部则取它

    iv) 然后重复这个操作,直到所有的类都被移除或者不可能找到好的磁头。

    O : 是对象类

    L[First] = 第一个 O

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

    现在求解 L[Second]

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

    First 是列表 FirstO 和列表 First 中的头,所以它是一个好头。

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

    O 是列表中唯一的头,它是好头

    L[Second] = Second + First + O

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

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

    现在求解 L[第三个]

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

    L[Third] = 第三个 + 不可能找到好的正面。

    First 是列表 FirstO 中的头,但它是列表 SecondFirstO 中的尾,Second 是列表 SecondFirstO 中的头,但它是列表 FirstSecond 中的尾,O 是列表 FirstO 和 SecondFirstO 中的尾,所以不可能找到好人头。

    【讨论】:

      猜你喜欢
      • 2018-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-21
      • 1970-01-01
      • 2011-08-01
      • 1970-01-01
      • 2023-03-24
      相关资源
      最近更新 更多