1、單繼承python
子類調用父類的一個方法,能夠用super():算法
class A(object):
def pp(self):
print('pp A')函數
class B(A):
def pp(self):
super().pp()
print("pp B")
b = B()
b.pp()繼承
#結果:
pp A
pp B
super()經常使用的方法是在__init__()方法中確保父類被正確的初始化了:原型
super(cls,inst).__init__() #cls,init 能夠省略
class A(object):
def __init__(self):
self.x = 1數學
class B(A):
def __init__(self):
super(B,self).__init__()
self.x = self.x +1
print(self.x)
b = B()it
#結果
2
也能夠直接調用父類的一個方法 :class
A.__init__(self)
class A(object):
def __init__(self):
self.x = 1原理
class B(A):
def __init__(self):
A.__init__(self)
self.x = self.x +1
print(self.x)
b = B()object
#結果
2
2、多繼承
super().xx方法能夠理解爲調用了父類中的方法xx,可是其實在單繼承中是這樣,而多繼承中有些區別
以下:
class A(object):
def __init__(self):
print("Enter A")
class B(A):
def __init__(self):
print('Enter B')
super(B,self).__init__()
print('Leave B')
class C(A):
def __init__(self):
print('Enter C')
super(C, self).__init__()
print('Leave C')
class D(B,C):
def __init__(self):
print('Enter D')
super(D,self).__init__()
print("Leave D")
d = D()
結果爲:
Enter D
Enter B
Enter C
Enter A
Leave C
Leave B
Leave D
若是按照本來的理解,是調用了B,C類中的方法,結果不會是這樣,那麼爲何會這樣呢?
實際上是咱們理解錯了super()
super()的用法:
1.super()的本質
先說說python中如何實現繼承---------對於你定義的每個類,Python會計算出一個所謂的方法解析順序(MRO)列表。 這個MRO列表就是一個簡單的全部基類的線性順序表。爲了實現繼承,Python會在MRO列表上從左到右開始查找基類,直到找到第一個匹配這個屬性的類爲止。
而這個MRO列表的構造是經過一個C3線性化算法來實現的。 咱們不去深究這個算法的數學原理,它實際上就是合併全部父類的MRO列表並遵循以下三條準則:
子類會先於父類被檢查
多個父類會根據它們在列表中的順序被檢查
若是對下一個類存在兩個合法的選擇,選擇第一個父類
雖然名義上來講super是用來調用父類中的方法,可是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 和父類其實沒有實質關聯,咱們就不難理解爲何 enter B 下一句是 enter C 而不是 enter A了(若是認爲 super 表明「調用父類的方法」,會想固然的認爲下一句應該是enter A)。
能夠用 self.__class__.__mro__ 方法來查詢當前MRO
MRO:
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
在個人理解裏,一個多繼承中的ORM是固定的(只要每一個類之間都有繼承關係)
上方例子的中流程:
首先是class D中,輸出「Enter D" , 而後就會調用super方法,super()方法,第一個參數是D,在MRO列表中的下標(index)爲0,那麼調用的下一個類就是下標爲(index+1)的類,即class B,
那麼進入class B,輸出"Enter B" ,再次調用super(),此時的index爲1,那麼調用的下一個類的index爲2,即class C,輸出「Enter C」 , 而後在class C中,調用super(),進入class A,輸出「Enter A」,而後回到class C ,輸出 "Leave C" , 再回到class B ,輸出「Leave B」, 而後回到class D,輸出「Leave D」。結束
當你使用 super() 函數時,Python會在MRO列表上繼續搜索下一個類。 只要每一個重定義的方法統一使用 super() 並只調用它一次, 那麼控制流最終會遍歷完整個MRO列表,每一個方法也只會被調用一次。