一. 经典类和新式类

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算法的更多相关文章

  1. python之路--MRO和C3算法

    一 . MRO(method resolution order) 多继承的一种方法,一种查找的顺序 在python3 里面是一种新类式MRO 需要用都的是C3算法 class A: pass clas ...

  2. Python的多继承问题-MRO和C3算法

    大部分内容转载自C3 线性化算法与 MRO 理解Python中的多继承 Python 中的方法解析顺序(Method Resolution Order, MRO)定义了多继承存在时 Python 解释 ...

  3. day21 MRO和C3算法

    核能来袭 --MRO和C3算法 1. python的多继承 2.python经典类的MRO 3.python新式类的MRO, C3算法 4.super 是什么鬼? 一.python的多继承 在前面的学 ...

  4. Python之MRO及其C3算法

    [<class '__main__.B'>, <class '__main__.A'>, <class 'object'>] (<class '__main_ ...

  5. python全栈开发day103-python垃圾回收机制、mro和c3算法解析、跨域jsonp\CORS、Content-Type组件

    Python垃圾回收 -- 引用计数 -- Python为每个对象维护一个引用计数 -- 当引用计数为0的 代表这个对象为垃圾 -- 标记清除 -- 解决孤立的循环引用 -- 标记根节点和可达对象 - ...

  6. python之MRO和C3算法

    python2类和python3类的区别pyhon2中才分新式类与经典类,python3中统一都是新式类Python 2.x中默认都是经典类,只有显式继承了object才是新式类python 3.x中 ...

  7. python MRO及c3算法

    1. 了解python2和python3类的区别 python2在2.3之前使用的是经典类, 2.3之后, 使用的是新式类 2. 经典类的MRO 树形结构的深度优先遍历 -> 树形结构遍历 cl ...

  8. python摸爬滚打之day20--多继承,MRO和C3算法

    1.新式类和经典类 在python2.2之前, 基类如果不写(), 则表示为经典类; 在python2.2之后, 经典类不复存在, 只存在新式类. 如果基类谁都不继承的话, 则默认继承object. ...

  9. Python新式类继承的C3算法

    在Python的新式类中,方法解析顺序并非是广度优先的算法,而是采用C3算法,只是在某些情况下,C3算法的结果恰巧符合广度优先算法的结果. 可以通过代码来验证下: class NewStyleClas ...

随机推荐

  1. 合并SCVMM虚拟机的差异磁盘,并删除那些难以删除的Checkpoints(Shapshots)

    使用Microsoft Data Protection Manager(DPM)有时会造成虚拟机的动态和固定磁盘变成差异磁盘,这个应该与DPM进行差异备份有关,未知原因造成DPM差异备份后无法复原原来 ...

  2. VisualStudio2012轻松把JSON数据转换到POCO的代码(转)

    VisualStudio2012轻松把JSON数据转换到POCO的代码 在Visual Studio 2012中轻松把JSON数据转换到POCO的代码,首先你需要安装Web Essentials 20 ...

  3. eclipse Android 开发基础 Activity 窗体 界面

    eclipse Android 开发基础 新建工程 新建布局layout,new Android Activity就相当于窗体Form. 新建Activity自动生成src下同名的java代码. pu ...

  4. delphi 触摸 手势

    delphi手势,左右滑动, 控件的OnGesture事件写代码. 放一个TGestureManager控件,设置控件的touch属性为TGestureManager控件. 然后勾选控件的Touch& ...

  5. ORA-12528问题解决

    这个问题说明数据库没有Mount 最好先将系统日志一并清空,避免以下报错信息: ERROR:ORA-28056: Writing audit records to Windows Event Log ...

  6. 获取当前函数名 __FUNCTION__ 的使用<转>

    vs项目中见过这种获取 当前函数名的调用.觉得挺方便的就记录一下. ============================================================== 转载地 ...

  7. jsp脚本语法

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...

  8. docker 网络配置路由转发

    建好flannel 网络之后 iptables -L -n 查看 要全是accept iptables -P FORWARD ACCEPT 开启路由转发 修改/etc/sysctl.conf文件,添加 ...

  9. 网页中给超链接添加"是否确认"的方法

    最近在做数据库, 需要给一个"删除"链接增加是否确认的弹出框, 在网上查到了两种方法: 1, 先看看最麻烦的一种 <html xmlns="http://www.w ...

  10. jsp生成好看的验证码

    这是一个Servlet,名字是ImageServlet package a; import java.awt.Color; import java.awt.Font; import java.awt. ...