Python多继承未遵循文档所述深度优先规则,求技术解答
Python多继承方法查找结果不符合预期的原因
问题代码
class B: def f(self): return "p" class C1(B): # 未定义f方法 pass class C2(B): def f(self): return "c2" class G(C1,C2): pass g = G() print("I would expect this value to be 'p'. But it prints 'c2'",g.f())
疑问描述
根据Python官方文档描述:
在大多数简单场景中,可将父类属性的搜索视为深度优先、从左到右的过程,不会在层级重叠的同一类中搜索两次。即若在派生类中未找到属性,会先在Base1中搜索,然后递归搜索Base1的基类,若仍未找到,再搜索Base2,以此类推。
但实际运行时,预期g.f()返回B类的"p",实际却输出C2类的"c2",这是哪里出了问题?
原因解析
问题出在对文档描述的适用场景理解偏差——当多继承存在共同基类时,Python的方法解析顺序(MRO)采用的是C3线性化算法,而非单纯的深度优先搜索。
可以通过打印G类的MRO验证顺序:
print(G.__mro__) # 输出:(<class '__main__.G'>, <class '__main__.C1'>, <class '__main__.C2'>, <class '__main__.B'>, <class 'object'>)
方法查找严格遵循这个顺序:
- G自身无
f方法,转向C1; - C1未定义
f,接下来不会直接跳去C1的基类B,而是按顺序查找C2; - C2有
f方法,直接返回其结果"c2"。
官方文档的描述是简化版,仅针对无共同基类的简单多继承场景。当存在共同父类时,C3算法会调整顺序,既保证共同基类只被搜索一次,又维护了子类继承的优先级顺序,避免方法查找出现歧义。
所以实际结果完全符合Python的MRO规则,只是你误将简化描述套用到了有共同基类的复杂场景中。
内容的提问来源于stack exchange,提问作者Dev LePeer
相关产品推荐
相关产品推荐

