前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于 Python3 MRO 的笔记

关于 Python3 MRO 的笔记

原创
作者头像
bowenerchen
发布2024-05-21 22:46:45
1400
发布2024-05-21 22:46:45
举报
文章被收录于专栏:编码视界编码视界

关于 MRO

MRO 的全称是:Method Resolution Order,从 Python2.3 开始,Python 使用 C3 算法来实现 Python 类继承时的线性解析逻辑。

Python 使用 C3 作为 MRO 算法的起因
Python 使用 C3 作为 MRO 算法的起因
C3 算法主要解决的问题
C3 算法主要解决的问题
C3 算法主要关注的特性
C3 算法主要关注的特性

关于 MRO 的更多信息可以到 Python 官网查看:https://docs.python.org/zh-cn/3/howto/mro.html#python-2-3-mro

关于 C3 算法的解释可以查看:https://en.wikipedia.org/wiki/C3_linearization

当然也可以去搜索C3 算法相关论文:《A Monotonic Superclass Linearization for Dylan》

Python中如何查看 MRO 属性

查看 MRO

代码语言:python
复制
class A(object):
    def hello(self):
        print(self.__class__, 'A')

if __name__ == '__main__':
    print('A MRO:', A.mro())
    A().hello()

上面是最简单的类定义,通过调用 A.mro()即可以看到被线性化的类列表。

最简单的 MRO 列表
最简单的 MRO 列表

带有继承关系时的 MRO

代码语言:python
复制
class A(object):
    def hello(self):
        print(self.__class__, 'A')

class B(A):
    def hello(self):
        print(self.__class__, 'B')

if __name__ == '__main__':
    print('B MRO:', B.mro())
    B().hello()

这里的继承比较简单直观,本身就是线性继承的,即 object --> A --> B,它的 MRO 长这样子:

线性继承
线性继承

带有多重继承关系时的 MRO

代码语言:python
复制
class A(object):
    def hello(self):
        print(self.__class__, 'A')

class B(object):
    def hello(self):
        print(self.__class__, 'B')

class C1(A, B):
    pass

class C2(B, A):
    pass

if __name__ == '__main__':
    print('C1 MRO:', C1.mro())
    C1().hello()

    print('C2 MRO:', C2.mro())
    C2().hello()

C1 和 C2 都继承了 A 和 B,只不过顺序不一样,此时他们的 MRO 和 hello 方法的执行逻辑发生了微妙的变化:

继承顺序与方法执行优先级关系
继承顺序与方法执行优先级关系

继承关系中的MRO决定了方法的查找顺序

代码语言:python
复制
class A(object):
    def hello(self):
        print(self.__class__, 'A')

class B(object):
    def hello(self):
        print(self.__class__, 'B')

class C1(A):
    pass

class C2(C1, B):
    pass

if __name__ == '__main__':
    print('C2 MRO:', C2.mro())
    C2().hello()
MRO 决定了成员函数的查找顺序
MRO 决定了成员函数的查找顺序

带有多重继承关系且具有公共基类时的 MRO

代码语言:python
复制
class A(object):
    def hello(self):
        print(self.__class__, 'A')

class B(A):
    def hello(self):
        print(self.__class__, 'B')

class C1(A):
    pass

class C2(C1, B):
    pass

if __name__ == '__main__':
    print('C2 MRO:', C2.mro())
    C2().hello()

此时 C1 和 B 都继承自 A,而 C2 又分别继承了 C1 和 B,且 C1 自身没有实现 hello 方法,B 自身实现了 Hello 方法,此时的 MRO 为:

具有公共基类的 MRO
具有公共基类的 MRO

总结:MRO 在 Python 中的几个关键作用

  • 确定属性和方法的搜索顺序:当Python查找一个类的属性或方法时,它会按照MRO定义的顺序去各个父类中搜索。
  • 解决多重继承中的冲突:在多重继承中,可能会有多个父类定义了相同名称的属性或方法。MRO定义了一个明确的搜索顺序,以解决这些潜在的冲突。
  • 支持合作式多重继承:Python支持合作式多重继承,这意味着子类可以从多个父类中继承方法,MRO确保了这些方法被合理地调用。
  • 提高代码的可读性和可维护性:通过明确类的方法解析顺序,开发者可以更容易地理解和预测代码的行为,从而提高代码的可读性和可维护性。
  • 动态查找父类:super()函数使用MRO来动态地查找父类中的方法,确保了方法调用的正确性。
  • 支持类的动态特性:Python的类是动态的,可以在运行时修改。MRO帮助Python解释器在这些动态变化中正确地解析方法和属性。
  • 帮助实现多态:MRO确保了当子类重写父类方法时,调用super()将按照正确的顺序调用父类的方法,支持了多态的实现。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于 MRO
  • Python中如何查看 MRO 属性
    • 查看 MRO
      • 带有继承关系时的 MRO
        • 带有多重继承关系时的 MRO
          • 继承关系中的MRO决定了方法的查找顺序
            • 带有多重继承关系且具有公共基类时的 MRO
            • 总结:MRO 在 Python 中的几个关键作用
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档