美文网首页
python中的MRO问题

python中的MRO问题

作者: 堆雪人的小朋友 | 来源:发表于2024-07-03 16:11 被阅读0次

一、背景

最开始遇到这个特性的场景是这样的:
有两个基类,已经开发好基础的接口,示例如下:

class A:
    def __init__(self):
        pass
    def func1(self):
        pass

class B:
    def __init__(self):
        pass
    def func2(self):
        pass

然后对外的接口需要分别调用A中的func1和B中的func2,尝试的方式是:

class C(A, B):
    def __init__(self):
        super().__init__()
    def run(self):
        self.func1()
        self.func2()

这样很简单完事。
上面的场景里涉及到一个知识点,多重继承。它的使用方式上最关键的点在于

class C(A, B):
    def __init__(self):
        super().__init__()

那这里的super的作用是什么?以及当一个类有多个继承关系的时候,是如何决定使用哪个类的方法的。

二、敲重点!

  1. super()是一个内置类,其完整版应该是接收两个参数,第一个是type,第二个是type或者是一个object,第二个参数决定了MRO链,第一个参数决定MRO链中起始位置。super()这一内置类能动态地根据MRO链来初始化函数。而不用程序员手动去一个一个继承类去分别初始化。

  2. 上面说到的MRO是什么?英文全称为Method Resolution Order,翻译中文为方法解析顺序。在python里,是支持继承其他类的方法和数据,而MRO就是python子类如何从父类中优先找继承的顺序。
    在很多简单的类继承的例子中,这种继承的先后顺序显而易见

class A:
    def say(self):
        print('my name is A')

class B:
    def say(self):
        print('my name is B')

class C(A):
    pass
class M(C, B):
    pass

m = M()
## M -> C -> A -> B
m.say()
## 'my name is A'

下面相对费解的继承关系是这样

class A:
    def say(self):
        print('my name is A')

class B(A):
    def say(self):
        print('my name is B')

class C(A):
    pass
class M(C, B):
    pass

m = M()
## M -> C -> B -> A
m.say()
## 'my name is B'

在python中的MRO里用到的算法为C3 linear,满足以下三个特性:
a. 扩展后的一致性
b. 局部优先顺序
c. 单调性

三、使用注意

  1. 继承结构要清晰明了,不要写非常复杂的继承污染代码;
  2. 对于不确定的继承关系,可以使用.mro()看看继承顺序;

四、参考链接

  1. https://www.bilibili.com/video/BV1V5411S7dY/?spm_id_from=333.337.search-card.all.click&vd_source=b7ee3c29ee2f1ad53bb1a4c3085932ff
  2. https://en.wikipedia.org/wiki/C3_linearization

相关文章

网友评论

      本文标题:python中的MRO问题

      本文链接:https://www.haomeiwen.com/subject/atgbcjtx.html