在【python】详解类class的继承、init初始化、super方法(五)详见链接一文中通过super的方法使得子类调用父类的属性或函数方法。正是因为class有方法解析顺序MRO。此文将详解MRO运行逻辑。
- Python的多继承类是通过MRO的方式来保证各个父类的函数被逐一调用,而且保证每个父类函数只调用一次(如果每个类都使用super)
- 混用super类和非绑定的函数是一个危险行为,这可能导致应该调用的父类函数没有调用或者一个父类函数被调用多次
假设现在有一个如下的继承结构,首先通过类名显示调用的方式来调用父类的初始化函数:
#父类A,调用时先print:Enter A,再Leave A
class A(object):
def __init__(self):
print( " ->Enter A")
print( " <-Leave A" )
#B类继承A类,B的初始化,先print:Enter B;
#再调用A父类的初始化,运行A父类初始化打印E: A,L: A;
#最后L: B。
class B(A):
def __init__(self):
print( " -->Enter B")
A.__init__(self)
print (" <--Leave B")
#C类继承A类,C的初始化,先print:Enter C;
#再调用A父类的初始化,运行A父类初始化打印E: A,L: A;
#最后L: C。
class C(A):
def __init__(self):
print (" --->Enter C")
A.__init__(self)
print (" <---Leave C")
#D类继承B、C类,先初始化进入D,print:Enter D
#先调用B类进行初始化,运行B类的初始化
#再调用C类进行初始化,运行C类的初始化
#最后打印:Leave D
class D(B, C):
def __init__(self):
print ("---->Enter D")
B.__init__(self)
C.__init__(self)
print( "<----Leave D")
d = D()
输出结果:
#D类继承B、C类,先初始化进入D,print:Enter D
---->Enter D
#先调用B类进行初始化,运行B类的初始化
-->Enter B
->Enter A
<-Leave A
<--Leave B
#再调用C类进行初始化,运行C类的初始化
--->Enter C
->Enter A
<-Leave A
<---Leave C
#最后打印:Leave D
<----Leave D
从输出中可以看到,类A的初始化函数被调用了两次,这不是我们想要的结果;我们通过super方式来调用父类的初始化函数:
class A(object):
def __init__(self):
print( " ->Enter A")
print( " <-Leave A" )
class B(A):
def __init__(self):
print( " -->Enter B")
super(B, self).__init__()
print (" <--Leave B")
class C(A):
def __init__(self):
print (" --->Enter C")
super(C, self).__init__()
print (" <---Leave C")
class D(B, C):
def __init__(self):
print ("---->Enter D")
super(D, self).__init__()
print( "<----Leave D")
d = D()
输出结果:
---->Enter D
-->Enter B
--->Enter C
->Enter A
<-Leave A
<---Leave C
<--Leave B
<----Leave D
通过输出可以看到,当使用super后,A的初始化函数只能调用了一次。这是由于Python的类有一个_ _mro _ 属性,这个属性中就保存着方法解析顺序。结合上面的例子来看看类D的 _ mro_ _:
print("MRO:", [x.__name__ for x in D.__mro__])
输出结果
MRO: ['D', 'B', 'C', 'A', 'object']
本文深入探讨了Python中类的继承机制,特别是在多继承情况下如何利用super方法正确调用父类构造函数,避免重复调用的问题。文章通过具体实例展示了传统调用方式与super方法的不同之处,并解释了方法解析顺序(MRO)的概念。
(六)&spm=1001.2101.3001.5002&articleId=79124212&d=1&t=3&u=2a019d0b282849dca7b0f850049bdea3)
1038

被折叠的 条评论
为什么被折叠?



