Python super繼承詳解

Dus發表於2015-02-08
MRO(Method resolution order)是python用來解析方法呼叫順序的,mro中記錄了一個類的所有基類的類型別序列,super不是簡單地呼叫基類的方法,而是按照MRO中的順序來呼叫類的方法。
使用super()時,應該在所有類中使用,否則就可能發生有的類建構函式沒有呼叫的情況。
 1 #!/usr/bin/python
 2 # -*- coding: utf-8 -*-
 3 class A(object):
 4     def __init__(self):
 5         print 'A __init__'
 6         super(A, self).__init__()
 7         print 'leave A'
 8 class C(object):
 9     def __init__(self):
10         print 'C __init__'
11         super(C, self).__init__()
12         print 'leave C'
13 class B(A,C):
14     def __init__(self):
15         print 'B __init__'
16         super(B, self).__init__()
17         print 'leave B'
18 class D(B):
19     def __init__(self):
20         print 'D __init__'
21         super(D, self).__init__()
22         print 'leave D'
23 if __name__ == '__main__':
24     D()
25 
26 輸出為:
27 D __init__
28 B __init__
29 A __init__
30 C __init__
31 leave C
32 leave A
33 leave B
34 leave D

 



編譯過程:super(D,self)查詢D的父類,根據廣度優先演算法依次查詢super(類名,self)的父類。

順便說一下 經典類和新式類的區別?

(1)在python2.x中,從object繼承得來的類稱為新式類(如class A(object))不從object繼承得來的類稱為經典類(如class A())
(2)
 新式類物件可以直接通過__class__屬性獲取自身型別:type
(3)繼承搜尋的順序發生了改變,經典類多繼承時屬性搜尋順序: 先深入繼承樹左側,再返回,開始找右側(即深度優先搜尋);新式類多繼承屬性搜尋順序: 先水平搜尋,然後再向上移動(即廣度優先搜尋)。

如下圖所示:

mro即method resolution order,主要用於在多繼承時判斷調的屬性的路徑(來自於哪個類)。

之前檢視了很多資料,說mro是基於深度優先搜尋演算法的。但不完全正確在Python2.3之前是基於此演算法,但從Python2.3起應用了新演算法:C3演算法。
為什麼採用C3演算法
C3演算法最早被提出是用於Lisp的,應用在Python中是為了解決原來基於深度優先搜尋演算法不滿足本地優先順序,和單調性的問題。
本地優先順序:指宣告時父類的順序,比如C(A,B),如果訪問C類物件屬性時,應該根據宣告順序,優先查詢A類,然後再查詢B類。
單調性:如果在C的解析順序中,A排在B的前面,那麼在C的所有子類裡,也必須滿足這個順序。
------------------------------新式類和舊式類中查詢屬性的順序不同-------------------------------------
在新式類中,查詢一個要呼叫的函式或者屬性的時候,是廣度優先搜搜的。
在舊式類當中,是深度優先搜尋的。

相關文章