day28 Pyhton MRO和C3算法
1.python多继承.一个类可以拥有多个父类
class ShenXian: # 神仙
def fei(self):
print("神仙都会飞")
class Monkey: # 猴
def chitao(self):
print("猴子喜欢吃桃子")
class SunWukong(ShenXian, Monkey): # 孙悟空是神仙, 同时也是一只猴
pass
sxz = SunWukong() # 孙悟空
sxz.chitao() # 会吃桃子
sxz.fei() # 会飞
此时, 孙悟空是一只猴子, 同时也是一个神仙. 那孙悟空继承了了这两个类. 孙悟空自然就可以执行行这两个类中的方法.
多继承用起来简单. 也很好理理解. 但是多继承中, 存在着这样一个问题. 当两个父类中出现了了重名方法的时候. 这时该怎么办呢? 这时就涉及到如何查找父类方法的这么一个问题.
即MRO(method resolution order) 问题. 在python中这是一个很复杂的问题. 因为在不同的python版本中使用的是不同的算法来完成MRO的. 首先. 我们目前能见到的有两个版本:
python2
在python2中存在两种类.
一个叫经典类. 在python2.2之前. 一直使用的是经典类. 经典类在基类的根如
果什什么都不写. 表示继承xxx.
一个叫新式类. 在python2.2之后出现了了新式类. 新式类的特点是基类的根是
object
python3
python3中使用的都是新式类. 如果基类谁都不继承. 那这个类会默认继承object
2.经典类的MRO
记住一个原则. 在经典类中采用的是深度优先
什什么是深度优先. 就是一条路路走到头. 然后再回来继续找下一个
3.新式类的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
加油, 最后了了
L(H) = (H, ) + (G, E, C, A) + ( F, D, B, E, C, A) -> H, G, 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'>)
C3是把我们多个类产生的共同继承留留到最后去找. 所以. 我们也可以从图上来看到相关的规律律. 这个要大家自己多写多画图就
能感觉到了了. 但是如果没有所谓的共同继承关系. 那几乎就当成是深度遍历就可以了.
4.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() # 报错
class Init(object):
def __init__(self, v):
print("init")
self.val = v
class Add2(Init):
def __init__(self, val):
print("Add2")
super(Add2, self).__init__(val)
print(self.val)
self.val += 2
class Mult(Init):
def __init__(self, val):
print("Mult")
super(Mult, self).__init__(val)
self.val *= 5
class HaHa(Init):
def __init__(self, val):
print("哈哈")
super(HaHa, self).__init__(val)
self.val /= 5
class Pro(Add2,Mult,HaHa): #
pass
class Incr(Pro):
def __init__(self, val):
super(Incr, self).__init__(val)
self.val+= 1
# Incr Pro Add2 Mult HaHa Init
# p = Incr(5)
# print(p.val)
#Add2
#Mult
#哈哈
#init
#5.0
#8.0
# c = Add2(2)
# print(c.val)
#Add2
#init
#2
#4
day28 Pyhton MRO和C3算法的更多相关文章
- day21 MRO和C3算法
核能来袭 --MRO和C3算法 1. python的多继承 2.python经典类的MRO 3.python新式类的MRO, C3算法 4.super 是什么鬼? 一.python的多继承 在前面的学 ...
- Python的多继承问题-MRO和C3算法
大部分内容转载自C3 线性化算法与 MRO 理解Python中的多继承 Python 中的方法解析顺序(Method Resolution Order, MRO)定义了多继承存在时 Python 解释 ...
- Python之MRO及其C3算法
[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>] (<class '__main_ ...
- python全栈开发day103-python垃圾回收机制、mro和c3算法解析、跨域jsonp\CORS、Content-Type组件
Python垃圾回收 -- 引用计数 -- Python为每个对象维护一个引用计数 -- 当引用计数为0的 代表这个对象为垃圾 -- 标记清除 -- 解决孤立的循环引用 -- 标记根节点和可达对象 - ...
- python之路--MRO和C3算法
一 . MRO(method resolution order) 多继承的一种方法,一种查找的顺序 在python3 里面是一种新类式MRO 需要用都的是C3算法 class A: pass clas ...
- python摸爬滚打之day20--多继承,MRO和C3算法
1.新式类和经典类 在python2.2之前, 基类如果不写(), 则表示为经典类; 在python2.2之后, 经典类不复存在, 只存在新式类. 如果基类谁都不继承的话, 则默认继承object. ...
- python之MRO和C3算法
python2类和python3类的区别pyhon2中才分新式类与经典类,python3中统一都是新式类Python 2.x中默认都是经典类,只有显式继承了object才是新式类python 3.x中 ...
- MRO和C3算法
本节主要内容: 1.python多继承 2.python经典类的MRO 3.python新式类的MRO,C3算法 4.super() 一.python多继承 在python中类与类之间可以有继承关系, ...
- python MRO及c3算法
1. 了解python2和python3类的区别 python2在2.3之前使用的是经典类, 2.3之后, 使用的是新式类 2. 经典类的MRO 树形结构的深度优先遍历 -> 树形结构遍历 cl ...
随机推荐
- SpringMVC-整合SSM
整合SSM 目录 整合SSM 1. 设计流程 2. 创建一个数据库表 3. 配置依赖 4. 准备项目框架 5. Mybatis层 1. 编写实体类 2. 编写Mapper接口和xml 1. Mappi ...
- 为商务办公赋能,TOM商务邮箱,塑造职场新形象
转眼已至2020年,互联网的这10年发生了翻天覆地的改变.短视频红利崛起.人脸识别支付.AI智能机器人对话...很多产品从默默无闻到一夜崛起.而对于商务邮箱领域,邮箱已成为一种习惯,却往往忽略了它的点 ...
- Redis统计访问量方法
1.统计客户忘问量 2.查询某位ID客户是否登录 一亿用户,统计数据10M左右,比较省空间 set usercount 0 设置一个变量,用于记录客户访问量setbit usercount 2 0 ...
- mongodb查询语句与sql语句对比
左边是mongodb查询语句,右边是sql语句.对照着用,挺方便. db.users.find() select * from users db.users.find({"age" ...
- 第24课 - #pragma 使用分析
第24课 - #pragma 使用分析 1. #pragma简介 (1)#pragma 是一条预处理器指令 (2)#pragma 指令比较依赖于具体的编译器,在不同的编译器之间不具有可移植性,表现为两 ...
- Node.js使用npm安装模块太慢,解决办法
转自 淘宝 npm 地址: http://npm.taobao.org/ 如何使用 有很多方法来配置npm的registry地址,下面根据不同情境列出几种比较常用的方法.以淘宝npm镜像举例: 1.临 ...
- 深度长文整理-Redis进阶
目录 一.基础 二.为什么Redis是单线程的? 三.为什么单线程这么快? 四.select.poll.epoll 五.Redis的事物 六.Redis的监控 七.Redis的配置文件 八.Redis ...
- 003.当在windows终端输入ipconfig时,显示不是内部或外部命令,也不是可运行的程序或批处理文件
当在windows终端输入ipconfig时,显示不是内部或外部命令,也不是可运行的程序或批处理文件,这是环境变量的问题: 右键我的电脑→→→属性→→→高级系统设置→→→(高级)环境变量 在弹出的窗口 ...
- 【运维】Vmware虚拟机静态IP的设置
这几天学习大数据,搭建的集群服务器由于Vmware内部实现的虚拟网关,动态分配ip,使得每次ip更改后,均需要修改集群节点的每个hosts文件,不然集群间联系会出错,因此为了杜绝这个问题,这里修改集群 ...
- php第五天-正则表达式,字符串的匹配与查找函数,数组切割
在php中有两套正则表达式,两者功能相似,一套是由PCRE,使用"preg_"为前缀命名的函数,一套是由POSIX拓展提供的,使用以"ereg_"命名的函数 0 ...