为什么这是一个模棱两可的 MRO?
Why is this 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")
Source
为什么不能 Python 创建一致的 MRO?在我看来很清楚:
- 如果方法在第三个中不存在,则在第一个中搜索
- 如果方法在第一个中不存在,则在第二个中搜索
但如果你尝试一下:
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution
order (MRO) for bases First, Second
要成为 "consistent",MRO 应满足以下限制条件:
- 如果一个class继承自多个超classes,它在superclass列表中较早列出的那些在MRO中应该比它较晚列出的那些更早。
- MRO 中的每个 class 都应该在它的任何超级 class 之前出现。
您提议的层次结构没有任何可能的顺序满足这些限制。因为 Third 被定义为从 First before Second 继承,所以在 MRO 中 First 应该在 Second 之前。但是因为 Second 继承自 First,所以在 MRO 中 Second 应该在 First 之前。这个矛盾无法调和。
您可以详细了解 Python 用于计算 MRO 的精确方法,称为 C3 linearization algorithm。
如果我们应用C3线性化算法:
i) 取第一个列表的头部。
ii) 如果这个头部不在任何其他列表的尾部,则将其添加到 C 的线性化中,并将其从合并中的列表中删除
iii) 否则看下一个表的头,是好头就拿
iv) 然后重复该操作,直到所有class被移除或者找不到好的头
O : 是对象 class
L[第一个]=第一个O
L[第二] = 第二 + 合并(L[第一], 第一)
现在求解L[第二个]
L[Second] = Second + merge(FirstO, First)
First是列表FirstO中的头,在列表First中,所以是个好头。
L[第二个]=第二个+第一个+合并(O)
O是列表中唯一的头,它是好头
L[第二个]=第二个+第一个+O
L[第二] = 第二个第一个 O
L[Third] = Third + merge(L[First], L[Second], FirstSecond)
现在求解L[Third]
L[Third] = Third + merge(FirstO, SecondFirstO, FirstSecond)
L[第三] = 第三 + 找不到好头。
First 是列表 FirstO 中的头部,但它是列表 SecondFirstO 中的尾部,Second 是列表 SecondFirstO 中的头部,但它是列表 FirstSecond 中的尾部,O 是列表 FirstO 中的尾部, SecondFirstO 所以不可能找到好的头。
Python 内部认为在 sub-class.
之前没有 super class
根据您的代码。扫描或加载 classes 后,Python 认为方法解析必须是:
Third -> Second -> First
这里,First是Second的超class。
但是在执行时,在检查 Third 之后它会遇到 First,它是 的超级 class第二.
因此出现类型错误。
class Third(First, Second): # Wrong
class Third(Second, First): # Correct
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?在我看来很清楚:
- 如果方法在第三个中不存在,则在第一个中搜索
- 如果方法在第一个中不存在,则在第二个中搜索
但如果你尝试一下:
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution
order (MRO) for bases First, Second
要成为 "consistent",MRO 应满足以下限制条件:
- 如果一个class继承自多个超classes,它在superclass列表中较早列出的那些在MRO中应该比它较晚列出的那些更早。
- MRO 中的每个 class 都应该在它的任何超级 class 之前出现。
您提议的层次结构没有任何可能的顺序满足这些限制。因为 Third 被定义为从 First before Second 继承,所以在 MRO 中 First 应该在 Second 之前。但是因为 Second 继承自 First,所以在 MRO 中 Second 应该在 First 之前。这个矛盾无法调和。
您可以详细了解 Python 用于计算 MRO 的精确方法,称为 C3 linearization algorithm。
如果我们应用C3线性化算法:
i) 取第一个列表的头部。
ii) 如果这个头部不在任何其他列表的尾部,则将其添加到 C 的线性化中,并将其从合并中的列表中删除
iii) 否则看下一个表的头,是好头就拿
iv) 然后重复该操作,直到所有class被移除或者找不到好的头
O : 是对象 class
L[第一个]=第一个O
L[第二] = 第二 + 合并(L[第一], 第一)
现在求解L[第二个]
L[Second] = Second + merge(FirstO, First)
First是列表FirstO中的头,在列表First中,所以是个好头。
L[第二个]=第二个+第一个+合并(O)
O是列表中唯一的头,它是好头
L[第二个]=第二个+第一个+O
L[第二] = 第二个第一个 O
L[Third] = Third + merge(L[First], L[Second], FirstSecond)
现在求解L[Third]
L[Third] = Third + merge(FirstO, SecondFirstO, FirstSecond)
L[第三] = 第三 + 找不到好头。
First 是列表 FirstO 中的头部,但它是列表 SecondFirstO 中的尾部,Second 是列表 SecondFirstO 中的头部,但它是列表 FirstSecond 中的尾部,O 是列表 FirstO 中的尾部, SecondFirstO 所以不可能找到好的头。
Python 内部认为在 sub-class.
之前没有 super class根据您的代码。扫描或加载 classes 后,Python 认为方法解析必须是:
Third -> Second -> First
这里,First是Second的超class。
但是在执行时,在检查 Third 之后它会遇到 First,它是 的超级 class第二.
因此出现类型错误。
class Third(First, Second): # Wrong
class Third(Second, First): # Correct