您的位置:首页 > 编程语言 > Python开发

python 多继承(新式类) 三

2013-08-26 22:22 369 查看
深入super

一下内容引用自:/article/6540351.html,写的挺好的。

代码段3


classA(object):#Amustbenew-styleclass
def__init__(self):
print"enterA"
print"leaveA"

classB(C):#A-->C
def__init__(self):
print"enterB"
super(B,self).__init__()
print"leaveB"


在我们的印象中,对于super(B,self).__init__()是这样理解的:super(B,self)首先找到B的父类(就是类A),然后把类B的对象self转换为类A的对象,然后“被转换”的类A对象调用自己的__init__函数。

有一天某同事设计了一个相对复杂的类体系结构(我们先不要管这个类体系设计得是否合理,仅把这个例子作为一个题目来研究就好),代码如下
代码段4:


classA(object):
def__init__(self):
print"enterA"
print"leaveA"

classB(object):
def__init__(self):
print"enterB"
print"leaveB"

classC(A):
def__init__(self):
print"enterC"
super(C,self).__init__()
print"leaveC"

classD(A):
def__init__(self):
print"enterD"
super(D,self).__init__()
print"leaveD"
classE(B,C):
def__init__(self):
print"enterE"
B.__init__(self)
C.__init__(self)
print"leaveE"

classF(E,D):
def__init__(self):
print"enterF"
E.__init__(self)
D.__init__(self)
print"leaveF"


f=F(),结果如下:

enterF
enterE
enterB
leaveB
enterC
enterD
enterA
leaveA
leaveD
leaveC
leaveE
enterD
enterA
leaveA
leaveD
leaveF

明显地,类A和类D的初始化函数被重复调用了2次,这并不是我们所期望的结果!我们所期望的结果是最多只有类A的初始化函数被调用2次——其实这是多继承的类体系必须面对的问题。我们把代码段4的类体系画出来,如下图:

object
|\
|A
|/|
BCD
\/|
E|
\|
F

按我们对super的理解,从图中可以看出,在调用类C的初始化函数时,应该是调用类A的初始化函数,但事实上却调用了类D的初始化函数。好一个诡异的问题!

也就是说,mro中记录了一个类的所有基类的类类型序列。查看mro的记录,发觉包含7个元素,7个类名分别为:

FEBCDAobject

  从而说明了为什么在C.__init__中使用super(C,self).__init__()会调用类D的初始化函数了。???

  我们把代码段4改写为:

代码段5:


classA(object):
def__init__(self):
print"enterA"
super(A,self).__init__()#new
print"leaveA"

classB(object):
def__init__(self):
print"enterB"
super(B,self).__init__()#new
print"leaveB"

classC(A):
def__init__(self):
print"enterC"
super(C,self).__init__()
print"leaveC"

classD(A):
def__init__(self):
print"enterD"
super(D,self).__init__()
print"leaveD"
classE(B,C):
def__init__(self):
print"enterE"
super(E,self).__init__()#change
print"leaveE"

classF(E,D):
def__init__(self):
print"enterF"
super(F,self).__init__()#change
print"leaveF"


f=F(),执行结果:

enterF
enterE
enterB
enterC
enterD
enterA
leaveA
leaveD
leaveC
leaveB
leaveE
leaveF

可见,F的初始化不仅完成了所有的父类的调用,而且保证了每一个父类的初始化函数只调用一次。

小结

  1.super并不是一个函数,是一个类名,形如super(B,self)事实上调用了super类的初始化函数,
产生了一个super对象;
  2.super类的初始化函数并没有做什么特殊的操作,只是简单记录了类类型和具体实例;
  3.super(B,self).func的调用并不是用于调用当前类的父类的func函数;
  4.Python的多继承类是通过mro的方式来保证各个父类的函数被逐一调用,而且保证每个父类函数
只调用一次(如果每个类都使用super);
  5.混用super类和非绑定的函数是一个危险行为,这可能导致应该调用的父类函数没有调用或者一
个父类函数被调用多次。

一些更深入的问题:各位可以看到,printF.__mro__时发现里面元素的顺序是FEBCDAobject,这就是F的基类查找顺序,至于为什么是这样的顺序,以及python内置的多继承顺序是怎么实现的,这涉及到mro顺序的实现,python2.3以后的版本中是采用的一个叫做C3的算法,在下篇博客中进行介绍。


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: