Python 之 super MRO (没有遇到过适用场景)
WOW!!!
這里wow的是真尼瑪繞且沒看完,
好困吶,貼上網址,等自己英文好一點再看(https://rhettinger.wordpress.com/2011/05/26/super-considered-super/),,,,
自己的理解:
先上例子:
例1:
class A(object):def __init__(self):print "enter A"print "leave A"class B(object):def __init__(self):print "enter B"print "leave B"class C(A):def __init__(self):print "enter C"super(C, self).__init__()print "leave C"class D(A):def __init__(self):print "enter D"super(D, self).__init__()print "leave D"class E(B, C):def __init__(self):print "enter E"B.__init__(self)C.__init__(self)print "leave E"class F(E, D):def __init__(self):print "enter F"E.__init__(self)D.__init__(self)print "leave F"輸出:
enter Fenter Eenter Bleave Benter Center Denter Aleave Aleave Dleave Cleave Eenter Denter Aleave Aleave Dleave F按我們對super的理解,從圖中可以看出,在調用類C的初始化函數時,應該是調用類A的初始化函數,但事實上卻調用了類D的初始化函數。好一個詭異的問題!并且類A和類D的初始化函數被重復調用了2次
這是為什么呢?
super不是簡單地調用所謂基類的方法,而是調用MRO中的下一個類的方法,也就是類似于next的方法。
mro中記錄了一個類的所有基類的類類型序列。查看mro的記錄,發覺包含7個元素,7個類名分別為:F E B C D A object
從而說明了為什么在C.__init__中使用super(C, self).__init__()會調用類D的初始化函數了。
不要一說到 super 就想到父類!super 指的是 MRO 中的下一個類!
MRO & super
Method resolution order是python用來解析方法調用順序的。MRO對于多重繼承中方法調用異常重要。python中有一個內建函數和MRO密切相關——super。具體實現方式,有興趣可以以后看看。
在 MRO 中,基類永遠出現在派生類后面,如果有多個基類,基類的相對順序保持不變。
super做了什么?
def super(cls, inst):mro = inst.__class__.mro()return mro[mro.index(cls) + 1]兩個參數 cls 和 inst 分別做了兩件事:
1. inst 負責生成 MRO 的 list
2. 通過 cls 定位當前 MRO 中的 index, 并返回 mro[index + 1]
super的作用是什么呢?
按名字繼承的話,如果子類的父類發生變化時,必須要全部替換名字,比較麻煩;
?
如果沒有復雜的繼承結構,super 作用不大。
例2:(沒太看懂這貨)
class A(object):def __init__(self):print "enter A"super(A, self).__init__() # new 寄幾繼承寄幾是什么鬼?print "leave A"class B(object):def __init__(self):print "enter B"super(B, self).__init__() # newprint "leave B"class C(A):def __init__(self):print "enter C"super(C, self).__init__()print "leave C"class D(A):def __init__(self):print "enter D"super(D, self).__init__()print "leave D"class E(B, C):def __init__(self):print "enter E"super(E, self).__init__() # changeprint "leave E"class F(E, D):def __init__(self):print "enter F"super(F, self).__init__() # changeprint "leave F"輸出:
enter Fenter Eenter Benter Center Denter Aleave Aleave Dleave Cleave Bleave Eleave F明顯地,F的初始化不僅完成了所有的父類的調用,而且保證了每一個父類的初始化函數只調用一次。
?
那么,總結:
1. super并不是一個函數,是一個類名,形如super(B, self)事實上調用了super類的初始化函數,?產生了一個super對象;
2. super類的初始化函數并沒有做什么特殊的操作,只是簡單記錄了類類型和具體實例;
3. super(B, self).func的調用并不是用于調用當前類的父類的func函數;
4. Python的多繼承類是通過mro的方式來保證各個父類的函數被逐一調用,而且保證每個父類函數只調用一次(如果每個類都使用super);
?
如果類被設計成使用了super,那么所有子類也必須要調用super,否則直接調用會出現重復調用的問題
?
5. 混用super類和非綁定的函數是一個危險行為,這可能導致應該調用的父類函數沒有調用或者一個父類函數被調用多次。(保持一致性。要不全部用類名調用父類,要不就全部用 super,不要一半一半。)
?
參考:
http://www.cnblogs.com/lovemo1314/archive/2011/05/03/2035005.html(super)
http://blog.csdn.net/rommi/article/details/51058360(MRO)
http://blog.csdn.net/seizef/article/details/5310107(super & MRO)?
??
轉載于:https://www.cnblogs.com/pannyvan/p/6135190.html
總結
以上是生活随笔為你收集整理的Python 之 super MRO (没有遇到过适用场景)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 20145202、20145225、20
- 下一篇: C#链接数据库增删改查的例子