Python 19 MRO和C3算法

1.python经典类的MRO

经典类的MRO

class A:
 	pass
class B(A):
 	pass
class C(A):
 	pass
class D(B, C):
 	pass
class E:
 	pass
class F(D, E):
 	pass
class G(F, D):
 	pass
class H:
    pass
class Foo(H, G):
 	pass

 

enter description here
enter description here

enter description here
enter description here

 

2. python新式类的MRO, C3算法

新式类的MRO

class A:
 	pass
class B(A):
 	pass
class C(A):
 	pass
class D(B, C):
 	pass
class E(C, A):
 	pass
class F(D, E):
 	pass
class G(E):
 	pass
class H(G, F):
 	pass
  • 首先. 我们要确定从H开始找. 也就是说. 创建的是H的对象.
    如果从H找. 那找到H+H的⽗类的C3, 我们设C3算法是L(x) , 即给出x类. 找到x的MRO
    L(H) = H + L(G) + L(F)
    继续从代码中找G和F的⽗类往⾥⾯带
    L(G) = G + L(E)
    L(F) = F + L(D)+ L(E)
    继续找E 和 D
    L(E) = E + L(C) + L(A)
    L(D) = D + L(B) + L(C)
    继续找B和C
    L(B) = B + L(A)
    L(C) = C + L(A)
  • 最后就剩下一个A了. 也就不用再找了. 接下来. 把L(A) 往回带. 再推回去. 但要记住. 这⾥的
    表示的是merge. merge的原则是⽤每个元组的头一项和后一元组的除头一项外的其他元
    素进行比较, 看是否存在. 如果存在. 就从下一个元组的头一项继续找. 如果找不到. 就拿出来.
    作为merge的结果的一项. 以此类推. 直到元组之间的元素都相同. 也就不⽤再找了.
    L(B) =(B,) + (A,) -> (B, A)
    L(C) =(C,) + (A,) -> (C, A)
    继续带.
    L(E) = (E,) + (C, A) + (A) -> E, C, A
    L(D) = (D,) + (B, A) + (C, A) -> D, B, A
    继续带.
    L(G) = (G,) + (E, C, A) -> G, E, C, A
    L(F) = (F,) + (D, B, A) + (E, C, A) -> F, D, B, E, C, A
    加油,
    算完了. 最终结果 HGFDBECA. 那这个算完了. 如何验证呢? 其实python早就给你准备好
    了. 我们可以使用类名.__mro__获取到类的MRO信息
print(H.__mro__)
结果: 
(<class '__main__.H'>, <class '__main__.G'>, <class '__main__.F'>, <class
'__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class'__main__.C'>,<class '__main__.A'>, <class 'object'>)

3. super是什么?

super()可以帮我们执行MRO中下一个父类的方法. 通常super()有两个使用的地方:

  1. 可以访问父类的构造方法
  2. 当子类方法想调用父类(MRO)中的方法
    方法一
class Foo:
    def __init__(self, a, b, c):
        self.a = a
 		self.b = b
        self.c = c
class Bar(Foo):
    def __init__(self, a, b, c, d):
 		super().__init__(a, b, c) # 访问父类的构造方法
 		self.d = d
b = Bar(1, 2, 3, 4)
print(b.__dict__)

结果: 
{'a': 1, 'b': 2, 'c': 3, 'd': 4}

方法二

class Foo:
    def func1(self):
        super().func1() # 此时找的是MRO顺序中下⼀个类的func1()方法
 		print("我的家. 就住在这个屯")
class Bar:
    def func1(self):
        print("你的家. 不在这个屯")
class Ku(Foo, Bar):
    def func1(self):
        super().func1() # 此时super找的是Foo
 		print("他的家. 不知道在哪个屯")
k = Ku() # 先看MRO . KU, FOO, BAR object
k.func1()
k2 = Foo() # 此时的MRO. Foo object
k2.func1() # 报错
posted @ 2018-11-19 17:04  恩佐MIG-U1  阅读(203)  评论(0编辑  收藏  举报