Python 经典类和新式类 super用法 (四)

来源:互联网 发布:dw淘宝全屏海报加热点 编辑:程序博客网 时间:2024/05/01 05:51

在Python2.x的2.2以上版本中,新式类是继承object的类。

经典类的MRO(基类搜索顺序)算法是深度优先。

新式类的MRO算法是C3算法。


经典类

class A:passclass B:passclass C(B):passclass D(C,A):pass
基类搜索顺序:

D->C->B,->A
[D,C,B,A]

新式类

class A(object):passclass B(object):passclass C(B):passclass D(A,B):passclass E(C,D):pass

C3算法:
class B(A1,A2,A3...):passmro(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]



0 0
原创粉丝点击