Python 經典類和新式類 super用法 (四)
阿新 • • 發佈:2019-02-14
在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演算法:
C3演算法的核心是merge演算法(查了半天資料才弄明白)class B(A1,A2,A3...):pass mro(B) = [B] + merge(mro(A1), mro(A2), mro(A3) ..., [A1,A2,A3])
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]
經典類和新式類例項
經典類
輸出為:1class 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
新式類
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]