返回顶部
首页 > 资讯 > 后端开发 > Python >MRO和C3算法
  • 901
分享到

MRO和C3算法

算法MRO 2023-01-30 22:01:19 901人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

本节主要内容: 1.python多继承 2.Python经典类的MRO 3.python新式类的MRO,C3算法 4.super()   一.python多继承 在python中类与类之间可以有继承关系,这也是面向对象的一大特征之一. 在

本节主要内容:

1.python多继承

2.Python经典类的MRO

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

4.super()

 

一.python多继承

在python中类与类之间可以有继承关系,这也是面向对象的一大特征之一.

在继承关系中,子类自动拥有父类中除了私有属性外的其他所有内容.python支持多继承.一个类可以拥有多个父类.

 

class Shen:
    def fly(self):
        print("大神会飞")
class Hou:
    def chi(self):
        print("猴子吃桃子")

class SunWuKong(Shen, Hou): # 一个类可以继承多个无关的类. 一个类可以被多个无关的类继承
    pass

class TaiShangLaoJun(Shen):
    pass


swk = SunWuKong()
swk.fly()
swk.chi()

此时,孙悟空是一只猴子,同时也是一个神仙.那孙悟空继承了这两个类.孙悟空自然就可以执行这两个类的方法.

在多继承中存在着这样一个问题.当两个父类中出现了重名方法的时候.该执行哪一个呢?这时就设计到如何查找父类方法的

这么一个问题.即MRO(method resolution order)问题. 在python中这时一个很复杂的问题.因为在不同的python版本中使用的

是不同的算法来完成MRO的.首先,我们目前能见到的两个版本:

·python2

在python2中存在两种类.

一个叫经典类.在python2.2之前使用的是经典类.经典类在基类的根如果什么都不写,表示继承xxx.

一个叫新式类.在python2.2之后出现了新式类.新式类的特点是基类的根是object

·python

python3中使用的都是新式类,如果基类谁都不继承,那这个类会默认继承object

 

二.经典类的MRO

经典类的MRO是通过树形结构的深度优先遍历.

在python的继承体系中,我们可以把类与类继承关系化成一个树形结构的图.

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.很简单.画图即可:

继承关系图已经有了.那如何进行查找呢?记住一个原则.在经典类中采用的是树形深度优先遍历方案.就是从下往上,从左子树

到右子树,一条路走到头.

所以上面的类的MRO为:Foo->H->G->F->D->B->A->C->E

三.新式类的MRO

python中的新式类的MRO采用的是C3算法来完成的.

C3算法不需要画图,我们只要看代码就可以了:

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 M(F, E):
    pass
class N:
    pass
class P(M,N):
    pass
class G(P):
    pass
class O:
    pass
class H(G, F):
    pass

 

首先.我们要确定从H开始找,也就是说.创建的是H的对象.

如果从H找,那找到H+H的父类的C3,我们设C3算法是L(x),即给出x类.找到的MRO

L(H) = H + L(G) + L(F) + (G,F)    

继续从代码中找G和F的父类往里面代

L(G) = G + L(E) +  (E,)       

L(F) = F + L(D)+ L(E) + (D,E)   

继续找E 和 D       

L(E) = E + L(C) + L(A) +(C,A)       

L(D) = D + L(B) + L(C) + (B,C)

继续找B和C       

L(B) = B + L(A) +  (A,)      

L(C) = C + L(A) + (A,)

最后就剩下一个A了,因为A没有父类所以不用再找了.接下来把L(A)往里面代,再推回去,但要记住,

这里的+表示的是merge.merge的原则是用每个院的头一项和后面元组的除头一项外的其他元素

进行比较,看是否存在.如果存在,就从下一个元组的头一项继续找,如果找不到,就拿出来.作为merge

的结果的一项.以此类推,直到元组之间的元素都相同了,也就不用再找了.

L(B) =(B,) + (A,) +(A,) -> (B, A)       

L(C) =(C,) + (A,) + (A,) -> (C, A)   

L(E) = (E,) + (C, A) + (A) +(C,A)  -> E, C, A       

L(D) = (D,) + (B, A) + (C, A) + (B,C)  -> D, B, A 

L(G) = (G,) + (E, C, A) -> G, E, C, A       

L(F) = (F,) + (D, B, A) + (E, C, A) + (D,E) -> F,  D, B,  E, C, A   

L(H) = (H, ) + (G, E, C, A) + ( F,  D,  B,  E, C, A) + (G,F)-> H, G, F, D, B, E, C, A 

最终的结果是HGFDBECA,那如何验证?其实python中可以使用类名.__mro__获取到类的MRO信息.

print(H.__mro__)
# 结果:
# (<class '__main__.Foo'>, <class '__main__.H'>, <class '__main__.G'>, <class '__main__.F'>, 
# <class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, 
# <class '__main__.E'>, <class 'object'>)

 

C3是把我们多个类产生的共同继承留到最后去找,所以,我们也可以从图上来看到相关的规律.这个要多写多画图

才能感觉到.但是如果没有所谓的共同继承关系,那就几乎就当成深度遍历就可以了.

以下是python官网关于MRO C3算法的文档地址:

https://www.python.org/download/releases/2.3/mro/

四.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(Bar, self).__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 ShengWu:
    def dong(self): # 实例方法
        print(self)
        print("我是生物")

class Animal(ShengWu):
   def dong(self):
        print("我是动物")
class Cat(Animal):
    def dong(self): # 子类中出现了和父类重名的内容. 表示对父类的方法的覆盖(重写). 半盖(java)
        super(Cat, self).dong()
        # super(Animal, self).dong() # 定位到Animal. 找Animal的下一个
        # super(类, 对象).方法()  找到MRO中的类. 找这个类的下一个. 去执行方法
        print("我的猫也会动")

 

 

最后是一个面试题:

# MRO + super ⾯试题
class Init(object):
    def __init__(self, v):
        print("init")
        self.val = v # 2
class Add2(Init):
    def __init__(self, val): # 2
        print("Add2")
        super(Add2, self).__init__(val)
        print(self.val) # 5.0
        self.val += 2 # 7.0
class Mult(Init):
    def __init__(self, val):
        print("Mult")
        super(Mult, self).__init__(val)
        self.val *= 5 # 5.0
class HaHa(Init):
    def __init__(self, val):
        print("哈哈")
        super(HaHa, self).__init__(val)
        self.val /= 5   # 1.0
class Pro(Add2,Mult,HaHa): #
    pass
class Incr(Pro):
    def __init__(self, val): # 5
        super(Incr, self).__init__(val)
        self.val += 1 # 8.0

        # Incr, pro, add2, mult, haha, Init
        p = Incr(5)
        print(p.val)  # ?
        # Add2 init
        c = Add2(2)
        print(c.val)  # ?
# 结果:
        '''
        add2
        Mult
        哈哈
        init
        5.0
        8.0
        Add2
        init
        2
        4
        
        '''

 

--结束END--

本文标题: MRO和C3算法

本文链接: https://lsjlt.com/news/180235.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • MRO和C3算法
    本节主要内容: 1.python多继承 2.python经典类的MRO 3.python新式类的MRO,C3算法 4.super()   一.python多继承 在python中类与类之间可以有继承关系,这也是面向对象的一大特征之一. 在...
    99+
    2023-01-30
    算法 MRO
  • C3 线性化算法与 MRO之Python中的多继承
    目录什么是 MRONew-style Class vs. Old-style Class理解 old-style class 的 MRO理解 new-style class 的 MR...
    99+
    2024-04-02
  • Python多继承解析顺序的C3线性算法
    Python多继承MRO 在Python2.1中,采用了经典类,使用深度优先算法解析。 Python2.2中,引入了新式类,使用深度优先算法和广度优先算法。 在Python2.3以后的版本中,经典类和新式类共存,使用了DFS算法和C3算法...
    99+
    2023-01-31
    线性 算法 顺序
  • Python学习之MRO方法搜索顺序
    目录为什么会讲 MRO?什么是 MRO注意MRO 算法什么是旧式类,新式类想深入了解 C3 算法的可以看看官网旧式类 MRO 算法新式类 MRO 算法新式 MRO 算法的问题什么是单...
    99+
    2024-04-02
  • C#递归算法和排列算法
    一、递归算法 递归:你打开面前这扇门,看到屋里面还有一扇门。你走过去,发现手中的钥匙还可以打开它,你推开门,发现里面还有一扇门,你继续打开它。若干次之后,你打开面前的门后,发现只有一...
    99+
    2024-04-02
  • JavaScript遍历实现DFS算法和BFS算法
    目录DFS(Depth first search)BFS(Breadth first search)总结DFS(Depth first search) Depth first sea...
    99+
    2023-01-14
    JavaScript实现DFS BFS JavaScript DFS BFS JavaScript DFS算法 JavaScript BFS算法
  • 数据结构和算法:算法复杂度
    我们开始了算法复杂度的学习,本期教程我们学习后半段。复杂度只考虑操作数目的一个数量级(忽略了其他的组分),这是一种近似。为了表示这种近似,我们使用一个特定的符号,就是著名的 大 O 符号。大 O 符号(Big O notation...
    99+
    2023-06-01
  • React的调和算法Diffing算法策略详解
    目录算法策略单节点diffing数组节点diffingkey值的使用要求算法策略 React的调和算法,主要发生在render阶段,调和算法并不是一个特定的算法函数,而是指在调和过程...
    99+
    2024-04-02
  • php回溯算法计算组合总和的方法
    本文小编为大家详细介绍“php回溯算法计算组合总和的方法”,内容详细,步骤清晰,细节处理妥当,希望这篇“php回溯算法计算组合总和的方法”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识...
    99+
    2024-04-02
  • java数据结构和算法之马踏棋盘算法
    本文实例为大家分享了java实现算法之马踏棋盘的具体代码,供大家参考,具体内容如下 一、马踏棋盘算法介绍 马踏棋盘算法也被称为骑士周游问题将马随机放在国际象棋的8×8棋盘...
    99+
    2024-04-02
  • C++图论之Bellman-Ford算法和SPFA算法的实现
    目录Bellman-Ford算法例题:AcWing 853. 有边数限制的最短路算法步骤代码实现SPFA算法代码实现给定一张有向图,若对于图中的某一条边(x,y,z),有dist[y...
    99+
    2024-04-02
  • PHP中如何进行排序算法和搜索算法?
    PHP作为一种常用的编程语言,其内置了许多排序和搜索算法来帮助开发者更有效地处理大量数据。本文将介绍一些常见的排序算法和搜索算法,并说明如何在PHP中使用它们。一、排序算法冒泡排序冒泡排序是一种基本的排序算法,它的原理是将相邻的元素两两比较...
    99+
    2023-05-20
    PHP排序算法 PHP搜索算法 排序和搜索算法
  • Java数据结构和算法之冒泡,选择和插入排序算法
    目录1、冒泡排序2、选择排序3、插入排序4、总结1、冒泡排序 这个名词的由来很好理解,一般河水中的冒泡,水底刚冒出来的时候是比较小的,随着慢慢向水面浮起会逐渐增大,这物理规律我不作过...
    99+
    2024-04-02
  • 【算法系列篇】前缀和
    文章目录 前言什么是前缀和算法1.【模板】前缀和1.1 题目要求1.2 做题思路1.3 Java代码实现 2. 【模板】二维前缀和2.1 题目要求2.2 做题思路2.3 Java代码实现...
    99+
    2023-09-10
    算法 前缀和
  • C#算法之两数之和
    题目 给定一个整数数组 nums和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每...
    99+
    2024-04-02
  • React中调和算法Diffing算法策略的示例分析
    这篇文章主要为大家展示了“React中调和算法Diffing算法策略的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“React中调和算法Diffing算法策略的示例分析”这篇文章吧。算法...
    99+
    2023-06-22
  • 求int32和int8的和的计算方法
    小伙伴们对Golang编程感兴趣吗?是否正在学习相关知识点?如果是,那么本文《求int32和int8的和的计算方法》,就很适合你,本篇文章讲解的知识点主要包括。在之后的文章中也会多多分享相关知识点,...
    99+
    2024-04-05
  • Python除法运算和幂运算代码实例
    “//”运算除法运算符是“/”,这个人人皆知道,但是这个二元运算符“/”求出来的结果都是取决于操作数本身的20 / 3620 / 3.06.66666666666666720.0 / 36.66666666666666720.0 / 3...
    99+
    2023-01-31
    除法 实例 代码
  • 【数据结构】-向上调整算法和向下调整算法
    作者:小树苗渴望变成参天大树 作者宣言:认真写好每一篇博客 作者gitee:gitee 如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧! 堆 前言一、堆的...
    99+
    2023-09-17
    数据结构 php 开发语言
  • 分析CAP和Paxos共识算法
    本篇内容介绍了“分析CAP和Paxos共识算法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!什么是 CAP...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作