首页 > 编程语言 >python C3算法

python C3算法

时间:2024-10-24 14:11:29浏览次数:1  
标签:K2 python K1 K3 merge 算法 pass C3 class

Python MRO

C3算法是python当中计算类继承顺序的一个算法,从python2.3以后就一直使用此算法了。

c3 linearization算法称为c3线性化算法

C3算法原理

首先定义几个符号的意义:

符号 意义
L 针对一个类进行解析用L进行表示,例如L(A)表示对类A进行解析
merge 合并操作的一个函数(后面具体介绍)
C 表示一个类名
B 表示是C的一个子类,如果多个子类用B1,B2....表示
+ 元素列表顺序添加
tail 去除列表第一个元素,例如 tail([1,2,3,4]) = [2,3,4]
L(C) = C + merge(L(B1) + L(B2) + ...+ )

merge函数合并规则:

  1. 首先选中merge 函数的第一个参数(也是一个列表),按照公式里的描述就是L(B1)。
  2. 取列表中第一个元素记为h,如果h没有出现其他 列表的tail中, 那么将其移到 merge函数前,提取出来,并且将这个元素在所有列表中移除,并重复 2。
  3. 如果出现在其他列表中的 tail 中,寻找下一个列表。
  4. merge 函数所有元素都被移除类创建成功,如果寻找不到下一个列表则创建失败。

下面举例说明:

image-20241024135943911

class X():
    pass

class Y():
    pass
        
class A(X, Y):
    pass
        
class B(X, Y):
     pass
         
class F(A, B):
    pass
print(F.__mro__)

我们来解析 F的mro顺序,则首先记为 L(F),根据

L(C) = C + merge(L(B1) + L(B2) + ...+ )

公式得到:

L(F) = F + merge(L(A)+L(B))

接下来计算L(A),与L(B):

L(A) = A + merge(L(X),L(Y)) = A + merge([X],[Y]) = [A,X,Y]
L(B) = B + merge(L(X),L(Y)) = B + merge([X],[Y]) = [B,X,Y]

带入 L(F) = L(F) + merge(L(A)+L(B)) 得到:

L(F) = F + merge([A,X,Y],[B,X,Y])

下面是关键merge逻辑理解了,首先根据 merge 的说明 1,选中得到 [A,X,Y], 根据merge的说明2,选中第一个元素 A, 判断A 是否在 tail(B,X,Y) 中,即 A 是否在 [X,Y] 中,不在,将其提出来,得到:

L(F) = F + merge([A,X,Y],[B,X,Y]) = [F,A] + merge([X,Y],[B,X,Y])

接着重复 merge的2,判断 X 是否在 tail(B,X,Y)=[X,Y] 中,结果是存在,那么寻找[X,Y]的下一个列表,即[B,X,Y],判断B 是否存在 tail([X,Y])=[Y] 中,不存在,提出B,得到:

L(F) = F + merge([A,X,Y],[B,X,Y]) = [F,A] + merge([X,Y],[B,X,Y]) = [F,A,B] + merge([X,Y],[X,Y])

剩下逻辑一样,依次提出 X和Y:

L(F) = F + merge([A,X,Y],[B,X,Y]) = [F,A] + merge([X,Y],[B,X,Y]) = [F,A,B] + merge([X,Y],[X,Y]) = [F,A,B,X,Y]

可以将我上述python代码运行一下结果和我们手算的是一样的:

(<class '__main__.F'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.X'>, <class '__main__.Y'>, <class 'object'>)

复杂的解析(练手逻辑)

image-20241024140042488

L(K1) = K1 + merge(L(C), L(A), L(B))
      = K1 + merge([C, O], [A, O], [B, O])
      = [K1, C] + merge([O], [A, O], [B, O])
      = [K1, C, A] + merge([O], [O], [B, O])
      = [K1, C, A, B] + merge([O], [O], [O])
      = [K1, C, A, B, O]
L(K2) = [K2, B,D,E, O]
L(K3) = [K3,A, D, O]
L(Z)  = Z + merge(L(K1), L(K3), L(K2))
      = Z + merge([K1, C, A, B, O],[K3, A, D, O],[K2, B, D, E, O])
      = [Z, K1] + merge([C, A, B, O], [K3, A, D, O], [K2, B, D, E, O])
      = [Z, K1, C] + merge([A, B, O], [K3, A, D, O], [K2, B, D, E, O])
      = [Z K1, C] + merge([A, B, O],  [K3, A, D, O], [K2, B, D,E, O])
      = [Z, K1, C, K3] + merge([A, B, O], [A, D, O], [K2, B, D, E, O])
      = [Z, K1, C, K3, A] + merge([B, O], [D, O],  [K2, B, D, E, O])
      = [Z,K1, C, K3, A, K2] + merge([B, O], [D, O], [B, D, E, O])
      = [Z,K1, C, K3, A, K2, B] + merge([O], [D, O], [D, E, O])
      = [Z, K1,C, K3, A, K2, B, D] + merge([O], [O], [E,O])
      = [Z, K1,C, K3, A, K2, B, D, E, O]
class O:
    pass

class C(O):
    pass

class A(O):
    pass

class B(O):
    pass

class D(O):
    pass

class E(O):
    pass

class K1(C,A,B):
    pass

class K3(A,D):
    pass


class K2(B,D,E):
    pass

class Z(K1,K3,K2):
    pass

print(Z.__mro__)

手写C3算法

def c3MRO(cls):
    if cls is object:
        # 讨论假设顶层基类为object,递归终止
        return [object]

    # 构造C3-MRO算法的总式,递归开始
    mergeList = [c3MRO(baseCls) for baseCls in cls.__bases__]
    mergeList.append(list(cls.__bases__))
    mro = [cls] + merge(mergeList)
    return mro


def merge(inLists):
    if not inLists:
        # 若合并的内容为空,返回空list
        # 配合下文的排除空list操作,递归终止
        return []

    # 遍历要合并的mro
    for mroList in inLists:
        # 取head
        head = mroList[0]
        # 遍历要合并的mro(与外一层相同),检查尾中是否有head
        ### 此处也遍历了被取head的mro,严格地来说不符合标准算法实现
        ### 但按照多继承中地基础规则(一个类只能被继承一次),
        ### head不可能在自己地尾中,无影响,若标准实现,反而增加开销
        for cmpList in inLists[inLists.index(mroList) + 1:]:
            if head in cmpList[1:]:
                break
        else:
            # 筛选出好head
            nextList = []
            for mergeItem in inLists:
                if head in mergeItem:
                    mergeItem.remove(head)
                if mergeItem:
                    # 排除空list
                    nextList.append(mergeItem)
            # 递归开始
            return [head] + merge(nextList)
    else:
        # 无好head,引发类型错误
        raise TypeError

参考文章:

c3 linearization详解 - Hello_wshuo - 博客园

Python多重继承问题之MRO和C3算法_Python_王坤祥_InfoQ写作社区

标签:K2,python,K1,K3,merge,算法,pass,C3,class
From: https://www.cnblogs.com/hnu-hua/p/18499493

相关文章

  • 栈的理解及相关算法
    一、栈的基础概念1、栈的定义栈(Stack):是只允许在一端进行插入或删除的线性表。首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作。栈顶(Top):线性表允许进行插入删除的那一端。栈底(Bottom):固定的,不允许进行插入和删除的另一端。空栈:不含任何元素的空表。栈又......
  • 单向循环链表的实现及相关算法
    1.单向循环链表特点:每一个节点除了数据域,还有一个next指针域指向下一个节点(存储了下一个节点的地址),末尾节点的指针域指向了头节点1.1实现过程1.1.1、构建结点structNode{ Node(intvalue=0): val(value), next(nullptr) {} intval; Node*next;};1......
  • Python的买家秀大揭秘:用代码点亮API数据
    在一个充满无限可能的数字世界里,Python侦探正准备开始他的新任务:揭开买家秀API数据的神秘面纱。这不仅是一次技术的挑战,更是一次与时间赛跑的较量。Python侦探,这位编程界的福尔摩斯,打开了他的笔记本电脑,准备开始这场冒险。Python侦探知道,要获取买家秀的API数据,他需要使用一些......
  • knime集成python实现当库存大于售出的80%发邮件给对应的客户实战案例
    数据样例:......
  • Python爬虫:爬取B站视频(详细讲解)
    Hello,大家好,我是南枫,今天带来什么项目呢?就是——爬B站视频。刷过B站的都知道,B站并没有下载功能,连官网都没有下载功能的话,那我们还能正常爬取吗?当然~首先我们要知道B站视频是分为视频和音频两部分,所以我们抓下来还不行,还需要把视频和音频给拼接起来。工作量乍一看感觉很大,其......
  • C#常见的四种经典查找算法
    前言在编程领域,数据结构与算法是构建高效、可靠和可扩展软件系统的基石。它们对于提升程序性能、优化资源利用以及解决复杂问题具有至关重要的作用。今天大姚给大家分享四种C#中常见的经典查找算法。C#数据结构与算法实战入门指南:https://mp.weixin.qq.com/s/XPRmwWmoZa4zq29K......
  • python_matlab图像去雾_去雨综述
    图像去雾和去雨是计算机视觉领域的两个重要任务,旨在提高图像质量和可视化效果。本文将综述图像去雾和去雨的算法、理论以及相关项目代码示例。一、图像去雾算法基于暗通道先验的方法:这是广泛应用于图像去雾的经典算法之一。该方法基于一个观察:自然场景中的大多数像素在......
  • 2024年韩顺平老师Python教程保姆级笔记
    代码获取:https://github.com/qingxuly/hsp_python_coursePython语言描述Python转义字符Python常用的转义字符转义字符说明\t制表符,实现对齐的功能\n换行符,\\一个\\"一个"\'一个'\r一个回车代码演示#\t制表符print("jack\t20")​#\n换行print("Hello,jack......
  • wrf-python安装教程
    记录一下wrf-python安装过程安装过程中出现了许多报错,这里记录了成功安装的完整流程。1.创建新环境#创建一个新环境推荐使用3.11版本condacreate-nWRFpython=3.11condaactivateWRF2.搭建Fortran环境1.安装visualstudio(自行前往官网下载)2.安装OneAPI(Base......
  • Python数据分析结合OpenAI:智能数据摘要和洞察
    Python数据分析结合OpenAI:智能数据摘要和洞察Python数据分析结合OpenAI:智能数据摘要和洞察在数据分析领域,随着数据集规模的日益庞大,如何从复杂的数据集中提取有价值的信息成为关键挑战。借助OpenAI的自然语言处理(NLP)能力,分析师可以自动生成摘要、报告,并获得有洞察力的结论......