在Python2.x的2.2以上版本中,新式类是继承object的类。
经典类的MRO(基类搜索顺序)算法是深度优先。
新式类的MRO算法是C3算法。
经典类
class A:pass
class B:pass
class C(B):pass
class D(C,A):pass
基类搜索顺序:
D->C->B,->A
[D,C,B,A]
新式类
class A(object):pass
class B(object):pass
class C(B):pass
class D(A,B):pass
class E(C,D):pass
C3算法:
class B(A1,A2,A3...):pass
mro(B) = [B] + merge(mro(A1), mro(A2), mro(A3) ..., [A1,A2,A3])
C3算法的核心是merge算法(查了半天资料才弄明白)
merge算法:如果一个序列的第一个元素,是其他序列中的第一个元素,或不在其他序列出现,则从所有执行merge操作序列中删除这个元素,合并到当前的mro中。
mro(A) = [A,O]
mro(B) = [B,O]
mro(C) = C + merge(mro(B),[B])
= C + merge([B,O],[B]) #merge中的第一个队列的第一个元素B是后面的元素的第一个元素,所以取出,并删除所有列表中该元素
= C + B + merge([O]) #第一个队列后面没有队列,所以没有该元素,所以取出,并删除所有列表中该元素
= C + B + O
= [C,B,O]
mro(D) = D + merge(mro(A),mro(B),[A,B])
= D + merge([A,O],[B,O],[A,B]) #merge中的第一个队列的第一个元素A不是后面的元素的第一个元素,但后面列表没有该元素,所以可以取出,并删除所有列表中该元素
= D + A + merge([O],[B,O],B) #merge中的第一个队列的第一个元素O不是后面的元素的第一个元素,后面队列中也有该元素,所以不能取出,然后判断第二个列表的第一个元素(如果还不符合条件,依次处理)
= D + A + merge([O],[B,O],B) #B是后面的元素的第一个元素,所以取出,并删除所有列表中该元素
= D + A + B + merge([O],[O]) #O是后面的元素的第一个元素,所以取出,并删除所有列表中该元素
= D + A + B + O
= [D,A,B,O]
mro(E) = E + merge(mro(C),mro(D),[C,D])
= E + merge([C,B,O],[D,A,B,O],[C,D]) #merge中的第一个队列的第一个元素C是后面的元素的第一个元素,所以可以取出,并删除所有列表中该元素
= E + C + merge([B,O],[D,A,B,O],[D]) #merge中的第一个队列的第一个元素B不是队列的第一个元素,且存在于其他队列,所以取第二个列表的第一个元素D,D满足要求,所以可以取出,并删除所有列表中该元素
= E + C + D + merge([B,O],[A,B,O]) #merge中的第一个队列的第一个元素B不是队列的第一个元素,且存在于其他队列,所以取第二个列表的第一个元素A,A满足要求,所以可以取出,并删除所有列表中该元素
= E + C + D + A + merge([B,O],[B,O]) #merge中的第一个队列的第一个元素B是后面的元素的第一个元素,所以可以取出,并删除所有列表中该元素
= E + C + D + A + B + merge([O],[O]) ##O是后面的元素的第一个元素,所以取出,并删除所有列表中该元素
= E + C + D + A + B + O
= [E,C,D,A,B,O]
这个算起来挺麻烦,所以类的继承还是不要写的那么复杂了,维护起来也很麻烦的。
经典类和新式类实例
经典类
class A():
ret = 1
def __init__(self):
pass
class B(A):
def __init__(self):
pass
class C(A):
ret = 2
def __init__(self):
pass
class D(B, C):
def __init__(self):
pass
#B->A->C
x = D()
print x.ret
输出为:1
新式类
class A(object):
ret = 1
def __init__(self):
pass
class B(A):
def __init__(self):
pass
class C(A):
ret = 2
def __init__(self):
pass
class D(B, C):
def __init__(self):
pass
#B->C->A
x = D()
print x.ret
输出为:2
super()
super(self,C).func() #调用的并不是其父类C的func,而是C在MRO中的下一个类的func,不能再经典类中使用
开始一直以为在多重继承的情况下选择执行某个父类的方法,网上有不少也是这么说的(被误导了)。
class A(object):
def __init__(self):
print "A"
class B(object):
def __init__(self):
print "B"
class C(object):
def __init__(self):
print "C"
class D(A,B,C):
def __init__(self):
super(D,self).__init__()
super(A,self).__init__()
super(B,self).__init__()
super(C,self).__init__()
X = D()
会发现:
super(D,self).__init__()
执行的是A.__init__()
super(A,self).__init__()
执行的是B.__init__()
super(B,self).__init__()
执行的是C.__init__()
super(C,self).__init__()
执行的是Object.__init__()
这是因为mro(D)为:[ D, A, B, C, Object]