MRO 方法搜索顺序 .mro

MRO是method resolution order,主要用于在对继承是判断方法、属性的调用路径【顺序】,其实也就是继承父类方法时的顺序表。Python中针对类提供了一个内置属性__mro__可以查看方法的搜索顺序。

class A:
    pass

class B:
    pass

class C(A,B):
    pass

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

super()

super 所代表的并不是简单的父类。完整的super()签名是:super(type, object_or_type=None),表示代理的是 MRO 序列中 type 的下一个类,它可能是 type 的父类,也可能是 type 的兄弟。无论是否有实际作用,在所有类的初始化方法中,都加上 super().init() 是一个好的习惯。

class A:
    def __init__(self):
        print("A enter")
        super().__init__()
        print("A exit")
        
    def add(self):
        print('A add enter')
        super().add()
        print('A add exit')

class B(A):
    def __init__(self):
        print("B enter")
        super().__init__()
        print("B exit")
        
    def add(self):
        print('B add enter')
        super().add()
        print('B add exit')
        

class C:
    def __init__(self):
        print("C enter")
        super().__init__()
        print("C exit")
        
    def add(self):
        print('C add enter')
        super().add()
        print('C add exit')

class E(A):
    def __init__(self):
        print("E enter")
        super().__init__()
        print("E exit")
        
    def add(self):
        print('E add enter')
        super().add()
        print('E add exit')

class D(B, C):
    def __init__(self):
        print("D enter")
        super().__init__()
        print("D exit")
        
    def add(self):
        print('D add enter')
        super().add()
        print('D add exit')

print(D.__mro__)  
d = D()
d.add()


//对于__init__(),调用顺序根据MRO为:D->B->A->C->object->object->C->A->B->D,因为object也有__init__()函数,所以能正常运行。
//对于add(),调用顺序根据MRO为:D->B->A->C->object->object->C->A->B->D,因为object没有add()函数,所以当执行到object.add()时,程序报错。

//output
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>)
D enter
B enter
A enter
C enter
C exit
A exit
B exit
D exit
D add enter
B add enter
A add enter
C add enter
Traceback (most recent call last):
File "c:\Users\CNMIZHU7\Source\repos\UtilityTools\PMTWUserScript\PythonTest.py", line 100, in <module>
    d.add()
File "c:\Users\CNMIZHU7\Source\repos\UtilityTools\PMTWUserScript\PythonTest.py", line 95, in add
    super().add()
File "c:\Users\CNMIZHU7\Source\repos\UtilityTools\PMTWUserScript\PythonTest.py", line 61, in add
    super().add()
File "c:\Users\CNMIZHU7\Source\repos\UtilityTools\PMTWUserScript\PythonTest.py", line 50, in add
    super().add()
File "c:\Users\CNMIZHU7\Source\repos\UtilityTools\PMTWUserScript\PythonTest.py", line 73, in add
    super().add()
    ^^^^^^^^^^^
AttributeError: 'super' object has no attribute 'add'

类属性和实例属性

python 的属性分为实例属性和类属性,实例属性是以self为前缀的属性,如果构造函数中定义的属性没有使用self作为前缀声明,则该变量只是普通的局部变量,类中其它方法定义的变量也只是局部变量,而非类的实例属性。