Py多重继承、MRO 及 C3算法之间的关系

简介: Py多重继承、MRO 及 C3算法之间的关系

学者须先立志。今日所以悠悠者,只是把学问不曾做一件事看,遇事则且胡乱恁地打过了,此只是志不立。——朱熹


1. 前言



在计算机科学中,C3算法主要用于确定多重继承时,子类应该继承哪一个父类的方法,即方法解析顺序(Method Resolution Order,MRO)。


2. C3算法实现了三种重要特性



  1. 保持继承拓扑图的一致性。
  2. 保证局部优先原则(又称:本地优先级,比如A继承C,C继承B,那么A读取父类方法,应该优先使用C的方法而不是B的方法)。
  3. 保证单调性原则(即子类不改变父类的方法搜索顺序,如:如果在C的解析顺序中,A排在B的前面,那么在C的所有子类里,也必须满足这个顺序)。


3. 为什么采用C3算法



C3主要用于在多继承时判断继承调用的路径(来自于哪个类)。

在Python2.3之前是基于深度优先算法,为了解决原来基于深度优先搜索算法不满足本地优先级,和单调性以及继承不清晰的问题,从Python2.3起应用了新的C3算法。在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之前的算法给出的顺序是GEFO, 而在C3算法中通过阻止类层次不清晰的声明来解决这一问题,以上声明在C3算法中就是非法的。


4. C3算法精讲



判断mro要先确定一个线性序列,然后查找路径由序列中类的顺序决定。所以C3算法就是生成一个线性序列。


如果继承至一个基类:
    class B(A)
这时B的mro序列为[B,A]
如果继承至多个基类:
    class B(A1,A2,...,An)
这时B的mro序列:
    mro(B) = [B] + merge(mro(A1), mro(A2),...,mro(An), [A1,A2,...,An])
merge操作就是C3算法的核心,是递归运算。


遍历执行merge操作的序列,如果一个序列的第一个元素,在其他序列中也是第一个元素,或不在其他序列出现, 则从所有执行merge操作序列中删除这个元素,合并到当前的mro中。merge操作后的序列,递归地执行merge操作,直到merge操作的序列为空。

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


例子1:

class A(object):pass
   class B(object):pass
   class C(object):pass
   class E(A,B):pass
   class F(B,C):pass
   class G(E,F):pass


A、B、C都继承至一个基类,所以mro序列依次为[A,O]、[B,O]、[C,O]

我们接下来看下E的mro如何求解:


mro(E) = [E] + merge(mro(A), mro(B), [A,B])
           = [E] + merge([A,O], [B,O], [A,B])


执行merge操作的序列为[A,O]、[B,O]、[A,B] A是序列[A,O]中的第一个元素,在序列[B,O]中不出现,在序列[A,B]中也是第一个元素, 所以从执行merge操作的序列([A,O]、[B,O]、[A,B])中删除A,合并到当前mro[E]中。


mro(E) = [E,A] + merge([O], [B,O], [B])


再执行merge操作,O是序列[O]中的第一个元素,但O在序列[B,O]中出现并且不是其中第一个元素。继续查看[B,O]的第一个元素B,B满足条件, 所以从执行merge操作的序列中删除B,合并到[E, A]中。


mro(E) = [E,A,B] + merge([O], [O])
           = [E,A,B,O]


同理


mro(F) = [F] + merge(mro(B), mro(C), [B,C])
           = [F] + merge([B,O], [C,O], [B,C])
           = [F,B] + merge([O], [C,O], [C])
           = [F,B,C] + merge([O], [O])
           = [F,B,C,O]
    mro(G) = [G] + merge(mro[E], mro[F], [E,F])
           = [G] + merge([E,A,B,O], [F,B,C,O], [E,F])
           = [G,E] + merge([A,B,O], [F,B,C,O], [F])
           = [G,E,A] + merge([B,O], [F,B,C,O], [F])
           = [G,E,A,F] + merge([B,O], [B,C,O])
           = [G,E,A,F,B] + merge([O], [C,O])
           = [G,E,A,F,B,C] + merge([O], [O])
           = [G,E,A,F,B,C,O]


例子2


再看一个复杂的例子:
    class A(object):pass
    class B(object):pass
    class C(object):pass
    class D(object):pass
    class E(object):pass
    class FA(A, B, C):pass
    class FB(D, B, E):pass
    class FC(D, A):pass
    class SF(FA, FB, FC): pass

你可以尝试着自己计算一下MRO List,当然,最后你需要用python自带的.mro()进行验证。


5.关注公众号



 微信公众号:堆栈future

相关文章
|
机器学习/深度学习 数据采集 算法
Py之scikit-learn:机器学习Sklearn库的简介、安装、使用方法(ML算法如何选择)、代码实现之详细攻略
Py之scikit-learn:机器学习Sklearn库的简介、安装、使用方法(ML算法如何选择)、代码实现之详细攻略
Py之scikit-learn:机器学习Sklearn库的简介、安装、使用方法(ML算法如何选择)、代码实现之详细攻略
|
6天前
|
算法 BI Serverless
基于鱼群算法的散热片形状优化matlab仿真
本研究利用浴盆曲线模拟空隙外形,并通过鱼群算法(FSA)优化浴盆曲线参数,以获得最佳孔隙度值及对应的R值。FSA通过模拟鱼群的聚群、避障和觅食行为,实现高效全局搜索。具体步骤包括初始化鱼群、计算适应度值、更新位置及判断终止条件。最终确定散热片的最佳形状参数。仿真结果显示该方法能显著提高优化效率。相关代码使用MATLAB 2022a实现。
|
6天前
|
算法 数据可视化
基于SSA奇异谱分析算法的时间序列趋势线提取matlab仿真
奇异谱分析(SSA)是一种基于奇异值分解(SVD)和轨迹矩阵的非线性、非参数时间序列分析方法,适用于提取趋势、周期性和噪声成分。本项目使用MATLAB 2022a版本实现从强干扰序列中提取趋势线,并通过可视化展示了原时间序列与提取的趋势分量。代码实现了滑动窗口下的奇异值分解和分组重构,适用于非线性和非平稳时间序列分析。此方法在气候变化、金融市场和生物医学信号处理等领域有广泛应用。
|
29天前
|
算法
基于模糊控制算法的倒立摆控制系统matlab仿真
本项目构建了一个基于模糊控制算法的倒立摆控制系统,利用MATLAB 2022a实现了从不稳定到稳定状态的转变,并输出了相应的动画和收敛过程。模糊控制器通过对小车位置与摆的角度误差及其变化量进行模糊化处理,依据预设的模糊规则库进行模糊推理并最终去模糊化为精确的控制量,成功地使倒立摆维持在直立位置。该方法无需精确数学模型,适用于处理系统的非线性和不确定性。
基于模糊控制算法的倒立摆控制系统matlab仿真
|
7天前
|
资源调度 算法
基于迭代扩展卡尔曼滤波算法的倒立摆控制系统matlab仿真
本课题研究基于迭代扩展卡尔曼滤波算法的倒立摆控制系统,并对比UKF、EKF、迭代UKF和迭代EKF的控制效果。倒立摆作为典型的非线性系统,适用于评估不同滤波方法的性能。UKF采用无迹变换逼近非线性函数,避免了EKF中的截断误差;EKF则通过泰勒级数展开近似非线性函数;迭代EKF和迭代UKF通过多次迭代提高状态估计精度。系统使用MATLAB 2022a进行仿真和分析,结果显示UKF和迭代UKF在非线性强的系统中表现更佳,但计算复杂度较高;EKF和迭代EKF则更适合维数较高或计算受限的场景。
|
9天前
|
算法
基于SIR模型的疫情发展趋势预测算法matlab仿真
该程序基于SIR模型预测疫情发展趋势,通过MATLAB 2022a版实现病例增长拟合分析,比较疫情防控力度。使用SIR微分方程模型拟合疫情发展过程,优化参数并求解微分方程组以预测易感者(S)、感染者(I)和移除者(R)的数量变化。![]该模型将总人群分为S、I、R三部分,通过解析或数值求解微分方程组预测疫情趋势。
|
9天前
|
算法 数据可视化 数据安全/隐私保护
基于LK光流提取算法的图像序列晃动程度计算matlab仿真
该算法基于Lucas-Kanade光流方法,用于计算图像序列的晃动程度。通过计算相邻帧间的光流场并定义晃动程度指标(如RMS),可量化图像晃动。此版本适用于Matlab 2022a,提供详细中文注释与操作视频。完整代码无水印。
|
24天前
|
算法 数据安全/隐私保护
基于LS算法的OFDM+QPSK系统信道估计均衡matlab性能仿真
基于MATLAB 2022a的仿真展示了OFDM+QPSK系统中最小二乘(LS)算法的信道估计与均衡效果。OFDM利用多个低速率子载波提高频谱效率,通过循环前缀克服多径衰落。LS算法依据导频符号估计信道参数,进而设计均衡器以恢复数据符号。核心程序实现了OFDM信号处理流程,包括加性高斯白噪声的加入、保护间隔去除、快速傅立叶变换及信道估计与均衡等步骤,并最终计算误码率,验证了算法的有效性。
43 2
|
24天前
|
算法
基于GA-PSO遗传粒子群混合优化算法的CVRP问题求解matlab仿真
本文介绍了一种基于GA-PSO混合优化算法求解带容量限制的车辆路径问题(CVRP)的方法。在MATLAB2022a环境下运行,通过遗传算法的全局搜索与粒子群算法的局部优化能力互补,高效寻找最优解。程序采用自然数编码策略,通过选择、交叉、变异操作及粒子速度和位置更新,不断迭代直至满足终止条件,旨在最小化总行驶距离的同时满足客户需求和车辆载重限制。
|
28天前
|
机器学习/深度学习 算法 定位技术
MATLAB - 遗传算法(GA)求解旅行商问题(TSP)
MATLAB - 遗传算法(GA)求解旅行商问题(TSP)
31 3