博弈论——两人取子游戏与威佐夫博弈,隐藏在背后的黄金分割dnf辅助Python 中的方式剖析顺序(Method Resolution Order, MRO)界说了多继续存在时 Python 注释器查找函数剖析的准确方式。当 Python 版本从 2.2 生长到 2.3 再到现在的 Python 3,MRO算法也随之发生了响应的转变。这种转变在许多时刻影响了我们使用差异版本 Python 编程的历程。

什么是 MRO

MRO 全称方式剖析顺序(Method Resolution Order)。它界说了 Python 中多继续存在的情形下,注释器查找函数剖析的详细顺序。什么是函数剖析顺序?我们首先用一个简朴的例子来说明。请仔细看下面代码:

class A():

def who_am_i(self):

print("I am A")

class B(A):

pass

class C(A):

def who_am_i(self):

print("I am C")

class D(B,C):

pass

d = D()

若是我问在 Python 2 中使用 D 的实例挪用 d.who_am_i(),事实执行的是 A 中的 who_am_i() 照样 C 中的 who_am_i(),我想百分之九十以上的人都市不假思索地回覆:一定是 C 中的 who_am_i(),由于 C 是 D 的直接父类。然而,若是你把代码用 Python 2 运行一下就可以看到 d.who_am_i() 打印的是 I am A。

是不是以为很杂乱很新鲜?感应新鲜就对了!!!

这个例子充实展示了 MRO 的作用:决议基类中的函数到底应该以什么样的顺序挪用父类中的函数。可以明确地说,Python 生长到现在,MRO 算法已经不是一个凭借着执行效果就能猜出来的算法了。若是没有深入到 MRO 算法的细节,稍微庞大一点的继续关系和方式挪用都能彻底绕晕你。

New-style Class vs. Old-style Class

在先容差异版本的 MRO 算法之前,我们有需要简朴地回首一下 Python 中类界说方式的生长历史。只管在 Python 3 中已经废除了老式的类界说方式和 MRO 算法,但对于仍然普遍使用的 Python 2 来说,差异的类界说方式与 MRO 算法之间具有慎密的联系。领会这一点将辅助我们从 Python 2 向 Python 3 迁移时不会泛起莫名其妙的错误。

在 Python 2.1 及以前,我们界说一个类的时刻往往是这个样子(我们把这种类称为 old-style class):

class A:

def __init__(self):

pass

Python 2.2 引入了新的模子工具(new-style class),其建议新的类型通过如下方式界说:

class A(object):

def __init__(self):

pass

注重后一种界说方式显示注明类 A 继续自 object。Python 2.3 及后续版本为了保持向下兼容,同时提供以上两种类界说用以区分 old-style class 和 new-style class。Python 3 则完全废弃了 old-style class 的观点,岂论你通过以上哪种方式誊写代码,Python 3 都将明确以为类 A 继续自 object。这里我们只是引入 old-style 和 new-style 的观点,若是你对他们的区别感兴趣,可以自行看 stackoverflow 上有关该问题的注释。

明了 old-style class 的 MRO

我们使用前文中的类继续关系来先容 Python 2 中针对 old-style class 的 MRO 算法。若是你在前面执行过那段代码,你可以看到挪用 d.who_am_i() 打印的应该是 I am A。为什么 Python 2 的注释器在确定 D 中的函数挪用时要先搜索 A 而不是先搜索 D 的直接父类 C 呢?

这是由于 Python 2 对于 old-style class 使用了异常简朴的基于深度优先遍历的 MRO 算法(关于深度优先遍历,我想人人一定都不生疏)。当一个类继续自多个类时,Python 2 凭据从左到右的顺序深度遍历类的继续图,从而确定类中函数的挪用顺序。这个历程详细如下:

检查当前的类内里是否有该函数,若是有则直接挪用。

检查当前类的第一个父类内里是否有该函数,若是没有则检查父类的第一个父类是否有该函数,以此递归深度遍历。

若是没有则回溯一层,检查下一个父类内里是否有该函数并凭据 2 中的方式递归。

上面的历程与尺度的深度优先遍历只有一点细微的差异:步骤 2 总是凭据继续列表中类的先后顺序来选择分支的遍历顺序。详细来说,类 D 的继续列表中类顺序为 B, C,因此,类 D 凭据先遍历 B 分支再遍历 C 分支的顺序来确定 MRO。

我们继续用第一个例子中的函数继续图来说明这个历程:

凭据上述深度递归的方式,函数 d.who_am_i() 挪用的搜索顺序是 D, B, A, C, A。由于一个类不能两次泛起,因此在搜索路径中去除掉重复泛起的 A,获得最终的方式剖析顺序是 D, B, A, C。这样一来你就明了了为什么 d.who_am_i() 打印的是 I am A 了。

在 Python 2 中,我们可以通过如下方式来查看 old-style class 的 MRO:

>>> import inspect

>>> inspect.getmro(D)

明了 new-style class 的 MRO

从上面的效果可以看到,使用深度优先遍历的查找算法并不合理。因此,Python 3 以及 Python 2 针对 new-style class 接纳了新的 MRO 算法。若是你使用 Python 3 重新运行一遍上述剧本,你就可以看到函数 d.who_am_i() 的打印效果是 I am C。

>>> d.who_am_i()

I am C

>>> D.__mro__

(, , , , )

新算法与基于深度遍历的算法类似,然则差异在于新算法会对深度优先遍历获得的搜索路径举行分外的检查。其从左到右扫描获得的搜索路径,对于每一个节点注释器都市判断该节点是不是好的节点。若是不是好的节点,那么将其从当前的搜索路径中移除。,绝地求生辅助,

那么问题在于,什么是一个好的节点?我们说 N 是一个好的节点当且仅当搜索路径中 N 之后的节点都不继续自 N。我们还以上述的类继续图为例,凭据深度优先遍历获得类 D 中函数的搜索路径 D, B, A, C, A。之后 Python 注释器从左向右检查时发现第三个节点 A 不是一个好的节点,由于 A 之后的节点 C 继续自 A。因此其将 A 从搜索路径中移除,然后获得最后的挪用顺序 D, B, C, A。

接纳上述算法,D 中的函数挪用将优先查找其直接父类 B 和 C 中的响应函数。

C3线性化算法

上一小结我们从直观上概述了针对 new-style class 的 MRO 算法历程。事实上这个算法有一个明确的名字 C3 linearization。下面我们给出其形式化的盘算历程。

上面的历程看起来似乎很庞大,我们用一个例子来详细执行一下,你就会以为实在照样挺简朴的。假设我们有如下的一个类继续关系:

class X():

def who_am_i(self):

print("I am a X")

class Y():

def who_am_i(self):

print("I am a Y")

class A(X, Y):

def who_am_i(self):

print("I am a A")

class B(Y, X):

def who_am_i(self):

print("I am a B")

class F(A, B):

def who_am_i(self):

print("I am a F")

Traceback (most recent call last):

File "test.py", line 17, in

class F(A, B):

TypeError: Cannot create a consistent method resolution

order (MRO) for bases X, Y

为什么接纳C3算法

上图中都是使用BFS算法来寻找继续链,然则都市有问题,左边的继续模式会违反单调性的原则,右边的棱形继续链,若是是C重写了继续于A的方式,B没有,然则凭据MRO继续链,最终挪用的都是A类的方式,C中实现的方式永远不会被挪用,这些都是再python2的问题,python引入C3算法后就解决了这些问题。

C3算法最早被提出是用于Lisp的,应用在Python中是为领会决原来基于深度优先搜索算法不知足内陆优先级,和单调性的问题。

内陆优先级:指声明时父类的顺序,好比C(A,B),若是接见C类工具属性时,应该凭据声明顺序,优先查找A类,然后再查找B类。

单调性:若是在C的剖析顺序中,A排在B的前面,那么在C的所有子类里,也必须知足这个顺序。

在Python官网的The Python 2.3 Method Resolution Order中作者举了例子,说明这一情形

F=type('Food', (), {remember2buy:'spam'})

E=type('Eggs', (F,), {remember2buy:'eggs'})

G=type('GoodFood', (F,E), {})

凭据内陆优先级在挪用G类工具属性时应该优先查找F类,而在Python2.3之前的算法给出的顺序是G E F O,而在心得C3算法中通过阻止类条理不清晰的声明来解决这一问题,以上声明在C3算法中就是非法的。

小结

C3算法的焦点 :

遍历执行merge操作的序列,若是一个序列的第一个元素,在其他序列中也是第一个元素,或不在其他序列泛起,则从所有执行merge操作序列中删除这个元素,合并到当前的mro中。

merge操作后的序列,继续执行merge操作,直到merge操作的序列为空。

若是merge操作的序列无法为空,则说明不合法。

参考资料

Task.Result跟 Task.GetAwaiter.GetResult()相同吗?怎么选?

python mro c3_绝地求生辅助_Python的多继续问题-MRO和C3算法相关推荐

  1. html 吃鸡游戏 源码,刺激战场 虚幻4引擎的和平精英来了 你会选择玩吗?-绝地求生辅助...

    今天相信很多刺激战场的玩家都比较大.早上上线的时候发现,战场其实已经不服务了.如果你不关心新闻,你一定很困惑. 但是如果你喜欢刷新闻,你就知道腾讯拿到了国内版本号<和平精英>.刚拿到版本号 ...

  2. 用Python可视化分析绝地求生上万场游戏数据,教你做最强吃鸡攻略啦~

    导语 大吉大利,今晚吃鸡~ 今天跟朋友玩了几把吃鸡,经历了各种死法,还被嘲笑说论女生吃鸡的100种死法,比如被拳头抡死.跳伞落到房顶边缘摔死 .把吃鸡玩成飞车被车技秀死.被队友用燃烧瓶烧死的.这种游戏 ...

  3. 利用Python做一个绝地求生“科学家”

    前言 玩吃鸡时间长的鸡友们 应该都知道现在的游戏环境非常差 特别在高端局 神仙满天飞 搞得很多普通玩家非常没有游戏体验,因为吃鸡的火爆,衍生出了一条巨大的外挂利益链,导致市面上出现了各式各样的外挂,正 ...

  4. 无法打开计算机 eploxre 接口未知,绝地求生辅助发卡网Win7系统打开计算机属性提示“此项目的属性未知”解决方案...

    windows7系统查看QQ好友ip地址的方法[图文] 最近有用户反映Win7系统打开电脑属性提示"这个项目属性未知".Win7系统为什么打不开电脑属性?Win7系统可以打开电脑属 ...

  5. 洗礼灵魂,修炼python(41)--巩固篇—从游戏《绝地求生-大逃杀》中回顾面向对象编程...

    声明:本篇文章仅仅以游戏<绝地求生>作为一个参考话题来介绍面向对象编程,只是作为学术引用,其制作的非常简易的程序也不会作为商业用途,与蓝洞公司无关. <绝地求生>最近很火,笼络 ...

  6. 绝地求生可以这样制作 (Python 版)

    一.概述 1.1 效果 总的来说,这种方式是通过图像识别来完成的,不侵入游戏,不读取内存,安全不被检测. 1.2 前置知识 游戏中有各种不同的枪械,不同的枪械后坐力不一样,射速也不同.相同的枪械,装上 ...

  7. 用Python写了个绝地求生(附源码)

    作者:LookOutTheBush https://juejin.cn/post/7232253274056785957 仅做学习交流,非盈利 一.概述 1.1 效果 总的来说,这种方式是通过图像识别 ...

  8. 基于Python的绝地求生数据分析吃鸡攻略可视化(包含报告、答辩PPT以及代码打包)

    1 选题背景及需求简介 为了让 PUBG 玩家体会到通关的快乐,需要尽可能准确地推测出吃鸡概 率与多种因素的关系.基于 python 的绝地求生吃鸡攻略可视化就是由此设计 开发的,通过输入不同条件,可 ...

  9. python新式类c3算法_python中的MRO和C3算法

    一. 经典类和新式类 1.python多继承 在继承关系中,python子类自动用友父类中除了私有属性外的其他所有内容.python支持多继承.一个类可以拥有多个父类 2.python2和python ...

最新文章

  1. Winform巧用窗体设计完成弹窗数值绑定-以重命名弹窗为例
  2. 关于Windows8.1更新后Sql Server服务消失的处理办法
  3. 阐述手机图像的贴图压缩技术标准及作用
  4. Android 系统性能优化(36)---显示性能指标
  5. JQ实现单击按钮 倒计时获取验证码
  6. php set_time_limit()的作用是什么
  7. canvas视频逐帧播放
  8. 10种软件滤波方法的示例程序
  9. 分享 Android 识音识别 挺有想法的。
  10. 如何提高测试工作效率
  11. vuecli3.0用scss写响应式网页,封装简单的百分比换算函数
  12. 创业公司系统安全的搭建
  13. postgresql立式版本下载_【PostgreSQL下载】PostgreSQL官方版下载_多特软件站
  14. 在电脑上如何录制游戏
  15. L2-048 寻宝图(25分)
  16. ubuntu下的android JNI入门DEMO
  17. vue按钮点击事件不传递到父控件
  18. r7000搭建php,新装NETGEAR R7000之折腾的最终完美结局
  19. python 端口扫描 东京_GitHub - w2n1ck/portscan: 一个基于Python+Go的端口扫描及服务探测脚本...
  20. 深度解析:5G与未来天线技术 5G通信到底需要什么样的天线?

热门文章

  1. 信息记录拉取失败_个税明细申报常见失败提示信息应对方法
  2. echarts地图中显示数字或省份
  3. Java 近期新闻:Classfile API 草案、Spring Boot、GlassFish、Reactor 项目、Micronaut
  4. ffmpeg编解码格式
  5. Webstorm2018激活和汉化详细步骤
  6. 九天揽月带你玩转EKF纸老虎(3)
  7. 计算机中怎样重新安装ps,【2人回答】电脑要重装系统,不想重装Photoshop CS6,怎么办?-3D溜溜网...
  8. 移动硬盘-移动硬盘提示格式化的解决办法
  9. 全面落地,2014大数据应用案例TOP100
  10. tf.keras.layers.BatchNormalization、tf.keras.layer.LayerNormalization函数