zoukankan      html  css  js  c++  java
  • 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() # 报错
    
  • 相关阅读:
    浅析NetFilter和iptables
    关于skb_header_pointer函数
    Linux kernel 绝对路径之d_path篇
    几个内核函数:filp_open、filp_read、IS_ERR、ERR_PTR、PTR_ERR
    一文读懂数字签名
    Nginx配置文件nginx.conf中文详解(总结)
    nginx 重写 rewrite 基础及实例
    最完美解决Nginx部署ThinkPHP项目的办法
    nginx中的try_files指令解释
    js电话号码正则校验--座机和手机号
  • 原文地址:https://www.cnblogs.com/NATO/p/9984066.html
Copyright © 2011-2022 走看看