阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

面向对象-mro

425次阅读
没有评论

共计 2723 个字符,预计需要花费 7 分钟才能阅读完成。

一、mro 概述

  • 概念

    方法解析顺序,是 python 中用于处理二义性问题的算法

  • 二义性

    问题一:有两个基类 A 类和 B 类,A 和 B 中都定义了 f()的方法,C 继承了 A 和 B,那么调用 C 的 f()方法时会出现不确定性

    问题二:有一个基类 A,定义了方法 f(),B 类和 C 类都继承自 A 类,D 类继承了 B 和 C 类,此时出现一个问题,D 类不知道继承 B 的 F()还是 C 的 F()

  • C++ 解决二义性

    问题一:通过同名覆盖的方法解决

    问题二:通过虚继承来解决

  • python 解决二义性

    通过 C3 算法避免二义性的情况

  • 经历过程

    a、python2.2 以前的版本(经典类时代)

    b、python2.2 版本(新式类诞生)

    c、python2.3 到 python2.7(经典类、新式类和平发展)

    d、python3 至今(新式类一统江山)

  • 示例代码

    class A(object): def f(self): pass class B(A): pass class C(A): pass class D(B, C): pass

二、python2.2 以前

经典类时代

  • 经典类

    特性:经典类是一种没有继承的类,对象都是 type 类型,如果经典类被作为父类,子类调用父类的构造函数时会出错

    class A: pass class B(A): pass
  • mro 的算法为深度优先算法(DFS)

    a、把根阶段压入栈结构中
    b、每次从栈中弹出一个元素,搜索所有它下一级元素,把这些元素压入栈中。并把这个元素记为它下一个元素的前驱
    c、找到所有的元素时程序结束
    d、如果遍历整个树还没有找到,程序结束

  • 两种继承模式(正常继承模式、菱形继承模式)

    # 正常继承模式 import inspect class D: pass class E: pass class B(D): pass class C(E): pass class A(B, C): pass print(inspect.getmro(A)) # A B D C E
    # 菱形继承模式 import inspect class D: pass class B(D): pass class C(D): pass class A(B, C): pass print(inspect.getmro(A)) # A B D C
  • MRO 的 DFS 顺序

    面向对象 -mro

  • 两种继承模式在 DFS 下的优缺点

    第一种:称为正常继承模式,两个互不相关的类的多继承,这种情况 DFS 顺序正常,不会引起任何问题

    第二种:棱形继承模式,存在公共父类(D)的多继承,这种情况下 DFS 必定经过公共父类(D),这时候想想,如果这个公共父类(D)有一些初始化属性或者方法,但是子类(C)又重写了这些属性或者方法,那么按照 DFS 顺序必定是会先找到 D 的属性或方法,那么 C 的属性或者方法将永远访问不到,导致 C 只能继承无法重写(override)。这也就是为什么新式类不使用 DFS 的原因,因为他们都有一个公共的祖先 object

三、python2.2

新式类诞生

  • 新式类

    特性:为了使类和内置的类型更加统一,引入新式类。新式类的每个类都继承于一个基类,可以是自定义的类或者其他类,默认是 object,子类可以调用父类的构造函数

  • 两种 MRO 算法

    • 如果是经典类使用 DFS

    • 如果是新式类使用 BSF(广度优先算法)

      a、把根阶段放到队列队尾

      b、每次从队列的头部取一个元素,搜索所有它下一级元素,把这些元素放到队列的末尾。并把这个元素记为它下一个元素的前驱

      c、找到所有的元素时程序结束

      d、如果遍历整个树还没有找到,程序结束

  • 两种继承模式(正常继承模式、菱形继承模式)

    # 正常继承模式 class D(object): pass class E: pass class B(D): pass class C(E): pass class A(B, C): pass print(A.__mro__) # A B C D E
    # 菱形继承模式 class D(objcet): pass class B(D): pass class C(D): pass class A(B, C): pass print(A.__mro__) # A B C D
  • MRO 的 BFS 顺序

    面向对象 -mro

  • 两种继承模式在 BFS 下的优缺点

    第一种:正常继承模式,看起来正常,但实际上感觉别捏,比如 B 继承 D 的 f()函数,恰巧 C 中也实现了 f()函数,那么 BFS 顺序先访问 B 在去访问 C,f()函数会选择 C 的,这种应该先从 B 和 B 的父类开始找才是正确的顺序,称为单调性

    第二种:菱形集成模式,在 BFS 模式下解决了 DFS 查找顺序的问题,但是它也违背了单调性

四、python2.3 到 python2.7

经典类与新式类和平发展

在之前的 BFS 算法存在很大的问题,从 python2.3 开始新式类的 MRO 算法使用 C3 算法,C3 算法解决了单调性问题和只能继承不能重写的问题

五、python3 时代

新式类一统江山

  • C3 算法

    C3 算法解决了单调性问题和只能继承无法重写问题

  • 两种继承模式(正常继承模式、菱形继承模式)

    # 正常继承模式 class D(object): pass class E: pass class B(D): pass class C(E): pass class A(B, C): pass print(A.__mro__)
    # 菱形继承模式 class D(objcet): pass class B(D): pass class C(D): pass class A(B, C): pass print(A.__mro__)
  • MRO 的 C3 顺序

    面向对象 -mro

  • 拓扑排序

    对一个有向无环图 (Directed Acyclic Graph 简称 DAG)G 进行拓扑排序,是将 G 中所有顶点排成一个线性序列,使得图中任意一对顶点 u 和 v,若边(u,v)∈E(G),则 u 在线性序列中出现在 v 之前。通常,这样的线性序列称为满足拓扑次序(Topological Order) 的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序

  • 模拟拓扑排序

    class D(object):
        pass
    class E(object):
        pass
    class F(object):
        pass
    class B(E, D):
        pass
    class C(D, F):
        pass
    class A(B, C):
        pass
    print(A.__mro__)
    # A B E C D F object
    

面向对象 -mro

首先找到入读点为 0 的点,只有一个 A,把 A 拿出来,把 A 相关的边裁剪掉,再找入读点为 0 的点,有两个(B、C)。根据最左侧原则,拿 B,此时的顺序 AB,把 B 相关的边裁剪掉。此时入读点为 0 的点有 E 和 C,取最左侧是 E,此时的顺序为 ABE。裁剪掉 E 的相关边,此时只有一个入读点为 0 的点为 C,取 C,此时的顺序是 ABEC。裁剪掉 C 的相关边,此时入读点为 0 的点有 D 和 F,取左侧的 D 点,此时的顺序为 ABECD,裁剪掉 D 的相关边,此时只有 F 的入读点为 0,取 F,此时的顺序 ABECDF,裁剪掉 F 的相关边,此时只有 object 入读点为 0,取 object,此时顺序为 ABECDFobject

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-05-26发表,共计2723字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19348
评论数
4
阅读量
7799184
文章搜索
热门文章
开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南

开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南

开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南 大家好,我是星哥。之前介绍了腾讯云的 Code...
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
云服务器部署服务器面板1Panel:小白轻松构建Web服务与面板加固指南

云服务器部署服务器面板1Panel:小白轻松构建Web服务与面板加固指南

云服务器部署服务器面板 1Panel:小白轻松构建 Web 服务与面板加固指南 哈喽,我是星哥,经常有人问我不...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
自己手撸一个AI智能体—跟创业大佬对话

自己手撸一个AI智能体—跟创业大佬对话

自己手撸一个 AI 智能体 — 跟创业大佬对话 前言 智能体(Agent)已经成为创业者和技术人绕...
2025年11月28日-Cloudflare史诗级事故:一次配置失误,引爆全球宕机

2025年11月28日-Cloudflare史诗级事故:一次配置失误,引爆全球宕机

2025 年 11 月 28 日 -Cloudflare 史诗级事故: 一次配置失误,引爆全球宕机 前言 继今...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
星哥带你玩飞牛NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手!

星哥带你玩飞牛NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手!

星哥带你玩飞牛 NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手! 作为动漫爱好者,你是否还在为...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
支付宝、淘宝、闲鱼又双叕崩了,Cloudflare也瘫了连监控都挂,根因藏在哪?

支付宝、淘宝、闲鱼又双叕崩了,Cloudflare也瘫了连监控都挂,根因藏在哪?

支付宝、淘宝、闲鱼又双叕崩了,Cloudflare 也瘫了连监控都挂,根因藏在哪? 最近两天的互联网堪称“故障...
自己手撸一个AI智能体—跟创业大佬对话

自己手撸一个AI智能体—跟创业大佬对话

自己手撸一个 AI 智能体 — 跟创业大佬对话 前言 智能体(Agent)已经成为创业者和技术人绕...
星哥带你玩飞牛NAS-8:有了NAS你可以干什么?软件汇总篇

星哥带你玩飞牛NAS-8:有了NAS你可以干什么?软件汇总篇

星哥带你玩飞牛 NAS-8:有了 NAS 你可以干什么?软件汇总篇 前言 哈喽各位玩友!我是是星哥,不少朋友私...
颠覆 AI 开发效率!开源工具一站式管控 30+大模型ApiKey,秘钥付费+负载均衡全搞定

颠覆 AI 开发效率!开源工具一站式管控 30+大模型ApiKey,秘钥付费+负载均衡全搞定

  颠覆 AI 开发效率!开源工具一站式管控 30+ 大模型 ApiKey,秘钥付费 + 负载均衡全...
开源MoneyPrinterTurbo 利用AI大模型,一键生成高清短视频!

开源MoneyPrinterTurbo 利用AI大模型,一键生成高清短视频!

  开源 MoneyPrinterTurbo 利用 AI 大模型,一键生成高清短视频! 在短视频内容...