python中的MRO和C3算法
一. 经典类和新式类
1.python多继承
在继承关系中,python子类自动用友父类中除了私有属性外的其他所有内容.python支持多继承.一个类可以拥有多个父类
2.python2和python3的区别
python2中存在两种类,一个叫经典类,在python2.2之前,一直使用的经典类.经典类是在基类的根如果什么都不写.表示继承xxx
另一个叫做心事类,在python2.2之后出现了心事类.新式类的特点是基类的根是object
python3中使用的都是新式类.如果基类谁都不继承,那这个类会默认继承object
二. 经典类的MRO
python早就为我们准备好了查看MRO的方法.可以使用类名.__mro__获取到累的MRO信息
1. 经典类的MRO 树型结构的深度优先遍历 --> 树形结构遍历
class Foo:
pass class Foo(object):
pass MRO: method resolution order 方法的查找顺序 class Base:
pass class Base1:
def chi():
pass class Bar(Base, Base1):
pass b = Bar() # Bar -> Base -> Base1
b.chi()
再举一个例子
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
来看关系图

进行深度优先遍历
MRO: Foo-> H -> G -> F -> D -> B -> A -> C -> E.
2. 新式类的MRO C3算法
C3方法解决顺序
让我介绍几个简单的符号,这些符号对以下讨论很有用。我将使用快捷方式表示法 C1 C2 ... CN
表示类别列表[C1,C2,...,CN]。 列表的头部是它的第一个元素: head = C1
而尾巴是列表的其余部分: tail = C2 ... CN。
我也会用这个符号 C +(C1 C2 ... CN)= C C1 C2 ... CN
表示列表的总和[C] + [C1,C2,...,CN]。 现在我可以解释MRO如何在Python 2.3中运行。 考虑多继承层次结构中的C类,其中C继承自基类B1,B2,...,BN。我们想要计算C类的线性化L [C]。规则如下: C的线性化是C的总和加上父母的线性化和父母的列表的合并。
用符号表示法: L [C(B1 ... BN)] = C +合并(L [B1] ... L [BN],B1 ... BN)
特别是,如果C是没有父项的对象类,则线性化是微不足道的: L [object] =对象。
但是,通常必须根据以下处方计算合并: 取第一个列表的头部,即L [B1] [0]; 如果这个头不在任何其他列表的尾部,那么将它添加到C的线性化并将其从合并中的列表中删除,否则查看下一个列表的头部并将其取出,如果它是好头。然后重复操作,直到所有课程都被移除或者找不到好头。在这种情况下,不可能构造合并,Python 2.3将拒绝创建类C并将引发异常。
如果可以保留排序,则此处方确保合并操作保留排序。另一方面,如果无法保留订单(如上面讨论的严重订单不一致的例子),则无法计算合并。 如果C只有一个父(单继承),那么合并的计算是微不足道的。在这种情况下 L [C(B)] = C +合并(L [B],B)= C + L [B]
官网解释 https://www.python.org/download/releases/2.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
把每个类转换为C3算法的形式
L(A) = A
L(B) = B + L(A) + A
L(C) = C + L(A) + A
L(D) = D + L(B) + L(C) + BC
L(E) = E + L(C) + L(A) + CA
L(F) = F + L(D) + L(E) + DE
L(G) = G + L(E) + E
L(H) = H + L(G) + L(F) + GF
之后我们来化简
加法:merge(), 拿第一项的第一位和 后面每项的除了第一位比较. 如果没有出现, 则该位元素算出
如果出现了. 此时开始下一项的第一位继续和后面每一项的除了第一位比较:
L(A) = A
L(B) = B + L(A) + A = BC
L(C) = C + L(A) + A = CA
L(D) = D + L(B) + L(C) + BC = D + BC + CA = DBCA
L(E) = E + L(C) + L(A) + CA = E + CA + A + CA = ECA
L(F) = F + L(D) + L(E) + DE = F + DBCA + ECA = FDBECA
L(G) = G + L(E) + E = G +ECA + E = GECA
L(H) = H + L(G) + L(F) + GF = H + GECA + FDBECA + GF = HGFDBECA
三. super
super() 找MRO顺序的下一个,通常有两个使用的地方:
1.可以访问父类的构造方法
2.当子类方法想调用父类(MRO)中的方法
来看一道面试题
# MRO + super ⾯面试题
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)
c = Add2(2)
print(c.val)
先算出MRO
L(Init) = Init
L(Add2) =Add2 + L(Init) + Init = Add2 , Init
L(Mult) = Mult + L(Init) + Init = Mult ,Init
L(HaHa) = HaHa + L(Init) + Init = HaHa,Init
L(Pro) = Pro +L(Add2) + L(Mult) + L(HaHa) + Add2,Mult,HaHa = Pro + Add2 , Init + Mult ,Init + HaHa,Init + Add2,Mult,HaHa = Pro,Add2,Mult,HaHa,Init
再进行运算

python中的MRO和C3算法的更多相关文章
- python之路--MRO和C3算法
一 . MRO(method resolution order) 多继承的一种方法,一种查找的顺序 在python3 里面是一种新类式MRO 需要用都的是C3算法 class A: pass clas ...
- Python的多继承问题-MRO和C3算法
大部分内容转载自C3 线性化算法与 MRO 理解Python中的多继承 Python 中的方法解析顺序(Method Resolution Order, MRO)定义了多继承存在时 Python 解释 ...
- day21 MRO和C3算法
核能来袭 --MRO和C3算法 1. python的多继承 2.python经典类的MRO 3.python新式类的MRO, C3算法 4.super 是什么鬼? 一.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算法
python2类和python3类的区别pyhon2中才分新式类与经典类,python3中统一都是新式类Python 2.x中默认都是经典类,只有显式继承了object才是新式类python 3.x中 ...
- python MRO及c3算法
1. 了解python2和python3类的区别 python2在2.3之前使用的是经典类, 2.3之后, 使用的是新式类 2. 经典类的MRO 树形结构的深度优先遍历 -> 树形结构遍历 cl ...
- python摸爬滚打之day20--多继承,MRO和C3算法
1.新式类和经典类 在python2.2之前, 基类如果不写(), 则表示为经典类; 在python2.2之后, 经典类不复存在, 只存在新式类. 如果基类谁都不继承的话, 则默认继承object. ...
- Python新式类继承的C3算法
在Python的新式类中,方法解析顺序并非是广度优先的算法,而是采用C3算法,只是在某些情况下,C3算法的结果恰巧符合广度优先算法的结果. 可以通过代码来验证下: class NewStyleClas ...
随机推荐
- ORA-12528问题解决
这个问题说明数据库没有Mount 最好先将系统日志一并清空,避免以下报错信息: ERROR:ORA-28056: Writing audit records to Windows Event Log ...
- Angular2中Input和Output
@Input @Input是用来定义模块的输入的,用来让父模块往子模块传递内容: @Output 子模块自定义一些event传递给父模块用@Output. 对于angular2中的Input和Outp ...
- 【320】Python 2.x 与 3.x 的区别
通过代码移植的报错进行梳理! 1. print 函数的区别 Python 2.x 中可以加空格或者括号,但是 Python 3.x 只能是括号的 # Python 2.x >>> p ...
- chrome36可以使用自定义元素的回调了
<!DOCTYPE html> <html> <head> <title>ms-attr-*</title> <meta charse ...
- 无法启动Tomcat, 端口被占用的问题
这个错误是说这几个端口已经有某个应用程序占用了,所以Tomcat就没法启动了. 出现这个问题的原因可能有以下几种: 情况一:点击运行的时候没有选中页面或Servlet窗口的标签 标签被选中时: 标 ...
- pyqt5 sip 段错误问题
在我装labelImg工具时,装了pyqt5,而后发现缺少sip模块,又pip安装上后,启动labelImg,报段错误. 经查资料,很容易发现,是pyqt5与sip版本不匹配造成的,具体缘由,可参看: ...
- CVE-2017-7494:Linux Samba named pipe漏洞
描述: 漏洞是由于代码中一个管道申请命令的判断导致的,可以通过构造特定请求执行上传的so文件. 漏洞影响了Samba 3.5.0 之后到4.6.4/4.5.10/4.4.14中间的所有版本. 测试: ...
- Django基础学习一
Django需要安装Django和jinja2,所以在开始学习之前,要先按照Django模块和jinja2模块,Django默认的数据库是SQLite,所以建议大家在学习之前需要先安装SQLite 一 ...
- Rotate image and fit show use canvas
Description In the field of image processing, We always to show image after modified the image raw d ...
- jdeveloper12.1.3的安装与卸载
jdeveloper12.1.3的安装步骤:1>安装jdk7.0 2>在命令行中输入:cd C:\Program Files\Java\jdk1.7.0_60\bin 3>命令行安装 ...