Skip to content

类属性和实例属性以及查找顺序

说明

  • MRO: Method Resolution Order

MRO 是在继承中使用的一个概念。它是在类层次结构中搜索方法的顺序,因为 Python 支持多重继承,所以,在 Python 类的设计及排错中特别有用。

  • DFS
  • BFS
  • C3

示例一

graph TB
    D((D)) --> B((B))
    D((D)) --> C((C))
    B((B)) --> A((A))
    C((C)) --> A((A))

查找顺序

  • 深度优先查找:A->B->D->C (错误)
  • 广度优先查找:A->B->C->D (正确)

深度优先查找的局限性

如果C重载了D的某个方法(B没有重载该方法), 由于深度优先的原则,B之后会优先查找D,结果将会使用D中的方法, 这是不合理的。

示例二

graph TB
    D((D)) --> B((B))
    E((E)) --> C((C))
    B((B)) --> A((A))
    C((C)) --> A((A))

查找顺序

  • 深度优先查找:A->B->D->C->E (正确)
  • 广度优先查找:A->B->C->D->E (错误)

广度优先查找的局限性

由于继承关系, B和D应该视为一个整体, B中查找不到相应方法,应该优先从其父类D中查找中, 但是由于广度优先, B之后会查找C,这时,如果C和D中定义了同名的方法, 最终结果将会使用C中的方法, 这是不合理的。

C3算法

# 新式类
class D:
    pass

class E:
    pass

class C(E):
    pass

class B(D):
    pass

class A(B, C):
    pass

print(A.__mro__)
#---------------------------------------
# A -> B -> D -> C -> E
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>)
class D:
    pass

class C(D):
    pass

class B(D):
    pass

class A(B, C):
    pass

print(A.__mro__)
#---------------------------------------
# A -> B -> C -> D
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)

拓展阅读