第二十天- 多繼承 經典MRO 新式MR

  • 2020 年 1 月 19 日
  • 筆記

# 多繼承:  # 在繼承關係中.⼦類自動擁有⽗類中除私有屬性外其他所有內容.python⽀持多繼承.子類可擁有多⽗類.
 1 class ShenXian: # 神仙   2   3  def fei(self):   4     print("神仙都會⻜")   5   6 class Monkey: # 猴   7   8  def chitao(self):   9     print("猴⼦喜歡吃桃⼦")  10  11 class SunWukong(ShenXian, Monkey): # 孫悟空是神仙, 同時也是⼀只猴(自己有先自己,然後靠最近的,再其他)  12     pass  13  14 # sxz = SunWukong() # 孫悟空  15 # sxz.chitao() # 會吃桃⼦  16 # sxz.fei() # 會⻜  17  18 # 這就是多繼承,但當兩個⽗類中出現了重名⽅法的時候.就涉及到如何查找⽗類⽅法的問題.  19 # 即下面的 MRO(method resolution order) 問題
# 經典類MRO演算法:  # 在python2.2之前用,現已棄用(做面試題參考) 採用的樹形結構的深度遞歸遍歷  # 方法:從頭開始.從左往右,一條道跑到底,然後回頭.繼續⼀條路跑到頭.(畫圖)
 1 # 畫圖排順序 現用python版本已無法驗證   2 class A:   3  pass   4 class B(A):   5  pass   6 class C(A):   7  pass   8 class D(B, C):   9  pass  10 class E:  11  pass  12 class F(D, E):  13  pass  14 class G(F, D):  15  pass  16 class H:  17  pass  18 class Foo(H, G):  19  pass  20  21 #  結果 : FOO--H--G--F--D--B--A--C--E

View Code

# 新式類MRO演算法(C3):  # 先拆後合 從下向上合併,拿出每一項的頭和後一項的身體進行比較.  # 如果出現了就過,從後一項的頭繼續去比較.如果不出現就出來放到結果。  # (注意:每次都是拿 頭一項 的頭和後面的身體比較,出現了就過,這時把後一項的頭作為頭一項繼續去比較,  # 若後一項的頭在後面身體還有,繼續這個操作...直到後面身體沒有再返回前面的頭,理解成一個循環)
 1 class A:   2     pass   3 class B(A):   4     pass   5 class C(A):   6     pass   7 class D(B, C):   8     pass   9 class E(C, A):  10     pass  11 class F(D, E):  12     pass  13 class M(F, E):  14     pass  15 class N:  16     pass  17 class P(M,N):  18     pass  19 class G(P):  20     pass  21 class O:  22     pass  23 class X(O):  24     pass  25 class H(G, X, F):  26     pass  27 print(H.__mro__)  28  29  30 '''  31 # 拆 注意別漏了末尾的 「GXF」  32 # 當類裡面只有單個繼承時不需要  33 L(H) = H + L(G) + L(X) + L(F) + GXF     HGPMXFDBECANO  34  35 L(G) = G + L(P)               GPMFDBECAN  36 L(X) = X + L(O)               XO  37 L(F) = F + L(D) + L(E) + DE   FDBECA  38  39 L(P) = P + L(M) + L(N) + MN   PMFDBECAN  40 L(O) = O  41 L(D) = D + L(B) + L(C) + BC    DBCA  42 L(E) = E + L(C) + L(A) + CA    ECA  43  44 L(M) = M + L(F) + L(E) + FE    MFDBECA  45  46 L(N) = N  47 L(B) = B + L(A)  BA  48 L(C) = C + L(A)  CA  49 L(A) = A  50  51  52 #  HGPMXFDBECANO

View Code

# super():  # super是查找mro順序中的下一個  # 單繼承中我們可以認為super是對父類中的屬性或方法的引入
# super()常用地方:  # 1.訪問⽗類的構造⽅法  # 2.⼦類⽅法調⽤⽗類(MRO)中的⽅法
 1 # 訪問⽗類的構造⽅法   2 class Foo1:   3  def __init__(self, a, b, c):   4     self.a = a   5     self.b = b   6     self.c = c   7 class Bar(Foo1):   8     def __init__(self, a, b, c, d):   9         super().__init__(a, b, c) # 訪問⽗類的構造⽅法 對父類中的屬性引入  10         self.d = d  11  12 b = Bar(1, 2, 3, 4)  13 print(b.__dict__)  # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
 1 # 當⼦類⽅法想調⽤⽗類(MRO)⽅法   2 class ShengWu:   3     def dong(self): # 實例方法   4         print(self)   5         print("我是生物")   6   7 class Animal(ShengWu):   8    pass   9  10 class Cat(Animal):  11     def dong(self): # 子類中出現了和父類重名的內容. 表示對父類的方法的覆蓋(重寫).  12         super(Animal, self).dong() # 定位到Animal. 找Animal的下一個  13         # super(類, 對象).方法()  找MRO中的類. 找這個類的下一個. 去執行方法  14         print("我的貓也會動")  15  16 # self 依然是誰調用就是誰  17 # 找MRO中的下一個  18 # Cat -> Animal -> ShengWu ->Object  19  20 c = Cat()  21 print(c)  22 c.dong()

View Code


# 總結 不管super()寫在哪⼉.在哪⼉執⾏.⼀定先找MRO列表.根據MRO列表的順序往下找.否則⼀切都是錯的