FreezeJ' Blog

MRO方法解析顺序

2019-04-28

MRO 方法解析顺序

Python 2.x 版本中,默认类都是旧式类,除非显式继承object。在Python 3.x 版本中,默认类就是新式类,无需显示继承object。新式类和经典类的多重继承方式不同(看版本),Python2.3起应用了新算法:C3算法。

MRO的全称是Method Resolution Order(方法解析顺序),它指的是一颗类继承树,
当调用最底层类对象所对应实例对象的方法时,Python解析器在类继承树上搜索方法的顺序。

# 以下代码由python2.7.5解析器执行
# MRO 方法解析顺序
class A(object):
    def say_hi(self):
        print('A hi!')


class B(A):
    def say_hi(self):
        print('B hi!')


class C(A):
    def say_hi(self):
        print('C hi!')


class D(B, C):
    pass


d = D()
d.say_hi()  # B hi!
print(D.mro())
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

print(D.__mro__)
# [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

可以通过类对象.mro()或者特殊方法__mro__来查看类对象的方法解析顺序。

直接使用super()方法来调用父类的方法时,也遵循mro。但是可以给super()方法传递参数,从而调用指定父类的方法。

# super() 与 MRO
class A(object):
    def say_hi(self):
        print('A hi!')


class B(A):
    def say_hi(self):
        print('B hi!')


class C(A):
    def say_hi(self):
        print('C hi!')


class D(B, C):
    def say_hi(self):
        super(B, self).say_hi()  # 调用MRO中B后面那个类的方法


d = D()
d.say_hi()  # C hi!
print(D.mro())
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
Tags: Python