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

在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]



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值