1. 程式人生 > >16 繼承 MRO和C3算法

16 繼承 MRO和C3算法

lap 回來 ani 一個 method 兩個 返回 __main__ code

一 多繼承

  • Python中類與類之間可以有繼承關系. 當出現了了x是一種y的的時候. 就可以使用繼承關系. 即"is-a" 關系. 在繼承關系中. 子類自動擁有父類中除了了私有屬性外的其他所有內容. python支持多繼承. 一個類可以擁有多個父類.
技術分享圖片
class ShenXian: # 神仙
    def fei(self):
        print("神仙都會飛")
class Monkey:   #
    def chitao(self):
        print("猴?喜歡吃桃子")
class SunWukong(ShenXian, Monkey): # 孫悟空是神仙, 同時也是一只猴
pass sxz = SunWukong() # 孫悟空 sxz.chitao() # 會吃桃?子 sxz.fei() # 會? #悟空既是猴子也是神仙所以可以多繼承,也就可以執行兩個類中的方法
View Code

  但是如果父類有重名的方法,又該先訪問誰餒?這時就涉及到如何查找父類方法的這麽一個問題。即MRO(method resolution order) 問題。在python中這是一個很復雜的問題。因為在不同的 python版本中使用的是不同的算法來完成MRO的。

  python2.3以前的解決方法:是深度優先遍歷方案,什麽是深度優先,就是一條路走到頭,然後再回來,繼續找下一個。

技術分享圖片

二、 目前python采用的是新式的MRoOo的算法,C3算法:

class A:
    pass
class B(A):
    pass
class C(A):
    pass
class D(B, C):
    pass
class E(C, A):
    pass
class F(D, E):
    pass
class G(E):
    pass
class H(G, F):
    pass

                                 步驟                    結果
L(H) = H + L(G) + L(F) + GF
H GECA FDBECA GF HGFDBECA L(G)
= G + L(E) + E G ECA E GECA L(F) = F + L(D) + L(E) + DE F DBCA ECA DE FDBECA L(E) = E + L(C) + L(A) + CA E CA A CA ECA L(D) = D + L(B) + L(C) + BC D BA CA BC DBCA L(B) = B + L(A) + A B A A BA L(C) = C + L(A) + A C A A CA L(A) = A A A print(H.mro()) # [<class ‘__main__.H‘>, <class ‘__main__.G‘>, <class ‘__main__.F‘>, <class ‘__main__.D‘>, <class ‘__main__.B‘>, # <class ‘__main__.E‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘object‘>]

具體算法使用最後一步說明 L(H) = H GECA FDBECA GF 一共四項對於每一項後面都要加上繼承的組合 GF,E,DE,CA等 ,從第一項 H 開始,和後面每一項除了他們的第一個字母比較如果後面項的‘身體’沒有出現H 則拿出來, 如果出現相同的 H 就先跳過第一項,拿出第二項第一個繼續和後面項的身體比較以此類推。根據這個例子:

1 首先 H 後面項身體沒出現所以提取H.

2.G和後面項比較後面項身體也沒有出現提取G(此刻刪除所有以G開頭項的G).

3.剩下 ECA FDBECA F 繼續比較E發現第二項身體有跳過第一項,使用第二項開頭的 F 和後面比較後面也沒有 提取 F(記得刪除 剩下的項 ECA DBECA) 此時提取出的有(HGF).

4.回到第一項使用E比較 發現還是有 繼續跳過 使用第二項 D比較後面 提取D.

5 返回第一項繼續拿到E 第二項依然有 依然拿到 B.

6.返回到第一項E比較此時第二項身體沒有E了 提取第一項E並刪除E 此刻剩下 CA CA 提取了 HGFDBE 所以後面兩項為CA.

三 supper()

技術分享圖片
class ShengWu:
    def dong(self): # 實例方法
        print(self)
        print("我是生物")

class Animal(ShengWu):
   def dong(self):
       print(我是動物)

class Cat(Animal):
    def dong(self): # 子類中出現了和父類重名的內容. 表示對父類的方法的覆蓋(重寫). 半蓋(java)
        super().dong()  #找到Animal
        super(Animal, self).dong() # 可以定位到Animal. 找Animal的下一個即生物
        # super(類, 對象).方法()  找到MRO中的類. 找這個類的下一個. 去執行方法
        print("我的貓也會動")
View Code

16 繼承 MRO和C3算法