欧美阿v视频在线大全_亚洲欧美中文日韩V在线观看_www性欧美日韩欧美91_亚洲欧美日韩久久精品

主頁 > 知識庫 > Python學習之MRO方法搜索順序

Python學習之MRO方法搜索順序

熱門標簽:哈爾濱外呼系統代理商 佛山防封外呼系統收費 南昌辦理400電話怎么安裝 電話機器人適用業務 湛江電銷防封卡 徐州天音防封電銷卡 不錯的400電話辦理 獲客智能電銷機器人 鄭州智能外呼系統運營商

為什么會講 MRO?

  • 在講多繼承的時候,有講到, 當繼承的多個父類擁有同名屬性、方法,子類對象調用該屬性、方法時會調用哪個父類的屬性、方法呢?
  • 這就取決于 Python 的 MRO 了

什么是 MRO

  • MRO,method resolution order,方法搜索順序
  • 對于單繼承來說,MRO 很簡單,從當前類開始,逐個搜索它的父類有沒有對應的屬性、方法
  • 所以 MRO 更多用在多繼承時判斷方法、屬性的調用路徑
  • Python 中針對類提供了一個內置屬性__mro__可以查看方法搜索順序

實際代碼

class A:
    def test(self):
        print("AAA-test")


class B:
    def test(self):
        print("BBB-test")


# 繼承了三個類,B、A、還有默認繼承的 object
class C(B, A):
    ...


# 通過類對象調用,不是實例對象!
print(C.__mro__)


# 輸出結果
(class '__main__.C'>, class '__main__.B'>, class '__main__.A'>, class 'object'>)

  • 1.在搜索方法時,是按照__mro__的輸出結果從左往右的順序查找的
  • 2.如果在當前類(Class C)中找到方法,就直接執行,不再搜索
  • 3.如果沒有找到,就查找下一個類中(Class B)是否有對應的方法,如果找到,就直接執行,不再搜素
  • 4.如果找到最后一個類(Class object)都沒有找到方法,程序報錯

類圖

注意

其實 MRO 是涉及一個底層算法的,下面來詳細講解一下

MRO 算法

Python 發展到現在經歷了三種算法

  • 舊式類 MRO 算法:從左往右,采用深度優先搜索(DFS),從左往右的算法,稱為舊式類的 MRO
  • 新式類 MRO 算法:自 Python 2.2 版本開始,新式類在采用深度優先搜索算法的基礎上,對其做了優化
  • C3 算法:自 Python 2.3 版本,對新式類采用了 C3 算法;由于 Python 3.x 僅支持新式類,所以該版本只使用 C3 算法

什么是舊式類,新式類

Python學習之新式類和舊式類講解

想深入了解 C3 算法的可以看看官網

https://www.python.org/download/releases/2.3/mro/

舊式類 MRO 算法

需要在 python2 環境下運行這段代碼

實際代碼

# 舊式類算法
class A:
    def test(self):
        print("CommonA")


class B(A):
    pass


class C(A):
    def test(self):
        print("CommonC")


class D(B, C):
    pass


D().test()


# python2 下的運行結果
CommonA

類圖

分析

  • 通過類圖可以看到,此程序中的 4 個類是一個“菱形”繼承的關系
  • 當使用 D 類實例對象訪問 test() 方法時,根據深度優先算法,搜索順序為D->B->A->C->A
  • 因此,舊式類 MRO 算法最先搜索得到 test() 方法是在 A 類里面,所以最終輸出結果為 CommonA

新式類 MRO 算法

  • 為解決舊式類 MRO 算法存在的問題,Python 2.2 版本推出了新的計算新式類 MRO 的方法
  • 它仍然采用從左至右的深度優先遍歷,但是如果遍歷中出現重復的類,只保留最后一個

以上面的代碼栗子來講

  • 深度優先遍歷,搜索順序為D->B->A->C->A
  • 因為順序中有 2 個 A,因此只保留最后一個
  • 最終搜索順序為D->B->C->A

新式 MRO 算法的問題

雖然解決了舊式 MRO 算法的問題,但可能會違反單調性原則

什么是單調性原則?

在子類存在多繼承時,子類不能改變父類的 MRO 搜索順序,否則會導致程序發生異常

實際代碼

class X(object):
    pass


class Y(object):
    pass


class A(X, Y):
    pass


class B(Y, X):
    pass


class C(A, B):
    pass

深度優先遍歷后的搜索順序為:C->A->X->object->Y->object->B->Y->object->X->object

相同取后者的搜索順序為:C->A->B->Y->X->object

分析不同類的 MRO

  • A:A->X->Y->object
  • B:A->Y->X->object
  • C:C->A->B->X->Y->object

很明顯,B、C 中間的 X、Y 順序是相反的,就是說 B 被繼承時,它的搜索順序會被改變,違反了單調性

在 python2 中運行這段代碼的報錯

在 python3 中運行這段代碼的報錯

C3 MRO 算法

  • 為解決前面兩個算法的問題,Python 2.3 采用了 C3 方法來確定方法搜索順序
  • 多數情況下,如果別人提到 Python 中的 MRO,指的都是 C3 算法

將上面第一個栗子的代碼放到 python3 中運行

class A:
    def test(self):
        print("CommonA")


class B(A):
    pass


class C(A):
    def test(self):
        print("CommonC")


class D(B, C):
    pass


D().test()


# 輸出結果
CommonC

簡單了解下 C3 算法

以上面代碼為栗子,C3 會把各個類的 MRO 等價為以下等式

  • A:L[A] = merge(A , object)
  • B:L[B] = B + merge(L[A] , A)
  • C:L[C] = C + merge(L[A] , A)
  • D:L[D] = D + merge(L[B] , L[C] , B , C)

了解一下:頭、尾

以 A 類為栗,merge() 包含的 A 成為 L[A] 的頭,剩余元素(這里只有 object)稱為尾

merge 的運算方式

  • 1.將merge 第一個列表的頭元素(如 L[A] 的頭),記作 H
  • 2.如果 H 出現在 merge 其他列表的頭部,則將其輸出,并將其從所有列表中刪除
  • 3.如果 H 只出現一次,那么也將其輸出,并將其從所有列表中刪除
  • 4.如果 H 出現在 merge 其他列表的非頭部,則取下一個列表的頭元素記作 H,然后回到步驟二
  • 5.最后回到步驟一,重復以上步驟

重復以上步驟直到列表為空,則算法結束;如果不能再找出可以輸出的元素,則拋出異常

簡單類 MRO 的計算栗子

class B(object): pass

print(B.__mro__)


(class '__main__.B'>, class 'object'>)
  • MRO 計算方式
L[B] = L[B(object)]
     = B + merge(L[object])
     = B + L[object]
     = B object

單繼承MRO 的計算栗子

# 計算 MRO
class B(object): pass

class C(B): pass

print(C.__mro__)


(class '__main__.C'>, class '__main__.B'>, class 'object'>)
  • MRO 計算方式
L[C] = C + merge(L[B])
     = C + L[B]
     = C B object

多繼承MRO 的計算栗子

O = object

class F(O): pass

class E(O): pass

class D(O): pass

class C(D, F): pass

class B(D, E): pass

class A(B, C): pass


print(C.__mro__)
print(B.__mro__)
print(A.__mro__)


# 輸出結果
(class '__main__.C'>, class '__main__.D'>, class '__main__.F'>, class 'object'>)
(class '__main__.B'>, class '__main__.D'>, class '__main__.E'>, class 'object'>)
(class '__main__.A'>, class '__main__.B'>, class '__main__.C'>, class '__main__.D'>, class '__main__.E'>, class '__main__.F'>, class 'object'>)

  • O 類、object 類 MRO 計算
L[O] = O = object
  • D、E、F 類 MRO 計算
L[D] = D + merge(L[O])
        = D O
  • C 類 MRO 計算
L[C] = L[C(D, F)]
     = C + merge(L[D], L[F], DF)
     # 從前面可知 L[D] 和 L[F] 的結果
     = C +  merge(DO, FO, DF)
     # 因為 D 是順序第一個并且在幾個包含 D 的 list 中是 head,
     # 所以這一次取 D 同時從列表中刪除 D
     = C + D + merge(O, FO, F)
     # 因為 O 雖然是順序第一個但在其他 list (FO)中是在尾部, 跳過
     # 改為檢查第二個list FO
     # F 是第二個 list 和其他 list 的 head
     # 取 F 同時從列表中刪除 F
     = C + D + F + merge(O)
     = C D F O
  • B 類 MRO 計算
L[B] = L[B(D, E)]
     = B + merge(L[D], L[E], DE)
     = B + merge(DO, EO, DE)
     = B + D + merge(O, EO, E)
     = B + D + E + merge(O)
     = B D E O
  • A 類 MRO 計算
L[A] = L[A(B,C)]
        = A + merge(L[B], L[C], BC)
        = A + merge( BDEO, CDFO, BC )
        = A + B + merge( DEO, CDFO, C )
        # D 在其他列表 CDFO 不是 head,所以跳過到下一個列表的 頭元素 C
        = A + B + C + merge( DEO, DFO )
        = A + B + C + D + merge( EO, FO )
        = A + B + C + D + E + merge( O, FO )
        = A + B + C + D + E + F + merge( O )
        = A B C D E F O

多繼承MRO 的計算栗子二

O = object

class F(O): pass

class E(O): pass

class D(O): pass

class C(D, F): pass

class B(E, D): pass

class A(B, C): pass


print(C.__mro__)
print(B.__mro__)
print(A.__mro__)


# 輸出結果
(class '__main__.C'>, class '__main__.D'>, class '__main__.F'>, class 'object'>)
(class '__main__.B'>, class '__main__.E'>, class '__main__.D'>, class 'object'>)
(class '__main__.A'>, class '__main__.B'>, class '__main__.E'>, class '__main__.C'>, class '__main__.D'>, class '__main__.F'>, class 'object'>)

  • O 類、object 類 MRO 計算
L[O] = O = object
  • D、E、F 類 MRO 計算
L[D] = D + merge(L[O])
        = D O
  • C 類 MRO 計算
L[C] = L[C(D, F)]
        = C + merge(L[D], L[F], DF)
        = C + merge(DO, FO, DF)
        = C + D + merge(O, FO, F)
        = C + D + F + merge(O)
        = C D F O
  • B 類 MRO 計算
L[B] = L[B(E, D)]
       = B + merge(L[E], L[D], ED)
       = B + merge(EO, DO, ED)
       = B + E + merge(O, DO, D)
       = B + E + D + merge(O)
       = B E D O
  • A 類 MRO 計算
L[A]  = L[A(B, C)]
        = A + merge(L[B], L[C], BC)
        = A + merge(BEDO, CDFO, BC)
        = A + B + merge(EDO, CDFO, C)
        = A + B + E + merge(DO,CDFO, C)
        = A + B + E + C + merge(O,DFO)
        = A + B + E + C + D + merge(O, FO)
        = A + B + E + C + D + F + merge(O)
        = A B E C D F O

到此這篇關于Python學習之MRO方法搜索順序的文章就介紹到這了,更多相關Python MRO方法搜索順序內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • 淺談Python的方法解析順序(MRO)
  • Python高級編程之繼承問題詳解(super與mro)
  • Python多繼承以及MRO順序的使用

標簽:懷化 吉安 蘭州 安康 紹興 蕪湖 廣西 呂梁

巨人網絡通訊聲明:本文標題《Python學習之MRO方法搜索順序》,本文關鍵詞  Python,學,習之,MRO,方法,搜索,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Python學習之MRO方法搜索順序》相關的同類信息!
  • 本頁收集關于Python學習之MRO方法搜索順序的相關信息資訊供網民參考!
  • 推薦文章
    欧美阿v视频在线大全_亚洲欧美中文日韩V在线观看_www性欧美日韩欧美91_亚洲欧美日韩久久精品
  • <rt id="w000q"><acronym id="w000q"></acronym></rt>
  • <abbr id="w000q"></abbr>
    <rt id="w000q"></rt>
    狠狠人妻久久久久久综合蜜桃| 欧美一区二区三区在线观看视频 | 国产乱国产乱300精品| 国产精品第七页| 欧美顶级少妇做爰| 亚洲超丰满肉感bbw| 91丨porny丨在线| 色999日韩国产欧美一区二区| 自拍av一区二区三区| 国产精品主播直播| 国产一二三av| 国产欧美1区2区3区| 国产一区二区0| av资源在线免费观看| 久久精品夜色噜噜亚洲aⅴ| 精品一区二区三区在线播放视频| 手机免费看av| 久久亚洲精精品中文字幕早川悠里| 久久国内精品视频| 中文字幕黄色网址| 欧美激情综合网| 成人中文字幕合集| 色诱亚洲精品久久久久久| 亚洲精品自拍动漫在线| 一区二区三区人妻| 91精品国产欧美一区二区18| 日韩高清电影一区| 蜜乳av中文字幕| 日本一区二区三区国色天香| 成人白浆超碰人人人人| 在线欧美日韩精品| 亚洲1区2区3区视频| 青青草视频播放| 久久综合五月天婷婷伊人| 国产呦精品一区二区三区网站| 九九这里只有精品视频| 专区另类欧美日韩| 亚洲熟妇一区二区| 精品国产一区二区国模嫣然| 国产福利一区二区三区视频在线| 色综合天天综合色综合av| 亚洲综合精品自拍| 亚洲永久精品ww.7491进入| 国产三级一区二区| 91美女片黄在线观看| 日韩一级片在线观看| 国产一区二区日韩精品| 色综合久久66| 热久久国产精品| 精品无码一区二区三区蜜臀| 亚洲精品国产品国语在线app| yy1111111| 欧美国产精品一区二区三区| 97se亚洲国产综合在线| 欧美一级欧美三级在线观看| 国产精品综合视频| 欧洲视频一区二区| 美腿丝袜亚洲色图| 中文字幕在线观看成人| 丝袜美腿高跟呻吟高潮一区| 午夜激情视频在线播放| 亚洲成av人片一区二区三区| 少妇视频在线播放| 亚洲免费高清视频在线| 国产原创剧情av| 国产女同性恋一区二区| 久久久久亚洲av无码专区首jn| 久久人人爽人人爽| 久久久久亚洲av无码网站| 久久久三级国产网站| 91免费精品国自产拍在线不卡| 欧美r级电影在线观看| va亚洲va日韩不卡在线观看| 日韩欧美精品在线| 99re这里都是精品| 久久久久高清精品| 99久久久无码国产精品性波多 | 久久久久久久网| 日本女人黄色片| av无码av天天av天天爽| 亚洲国产精品ⅴa在线观看| 9.1在线观看免费| 国产精品美女久久久久av爽李琼| 中文字幕在线视频播放| 1000精品久久久久久久久| 一级片视频免费看| 亚洲第一会所有码转帖| 小早川怜子一区二区的演员表| 日韩高清电影一区| 欧美色精品天天在线观看视频| 国产一区二区三区免费在线观看| 欧美精品日韩一本| 懂色av中文一区二区三区 | 欧美一区二区三区在线看| youjizz国产精品| 久久网站最新地址| 老司机免费视频| 伊人性伊人情综合网| 亚洲AV成人无码网站天堂久久| 日韩**一区毛片| 欧美猛男超大videosgay| 成人精品一区二区三区四区 | 日本国产一区二区| 国产一区二区日韩精品| 欧美大片在线观看一区二区| 乱码一区二区三区| 亚洲少妇最新在线视频| 成人高清免费在线播放| 国产精品传媒视频| 欧美性生给视频| 亚洲女性喷水在线观看一区| 国产精品久久久久久成人| 免费在线观看一区| 91精品国产欧美一区二区成人| 黑人性生活视频| 一区二区在线看| 一本大道av伊人久久综合| 成人国产免费视频| 国产精品国产三级国产普通话三级 | 亚洲国产精品尤物yw在线观看| 色婷婷国产精品| 成人毛片视频在线观看| 中文字幕第一区二区| 日韩av毛片在线观看| 国产在线观看一区二区| 久久综合九色综合欧美亚洲| 中文字幕在线看高清电影| 日韩高清在线不卡| 日韩欧美不卡在线观看视频| 手机在线看片日韩| 青青草国产成人99久久| 欧美成人一区二区三区片免费| 97香蕉碰碰人妻国产欧美 | 91精品婷婷国产综合久久竹菊| 中文字幕天堂网| 丝袜脚交一区二区| 精品免费日韩av| 男人的天堂官网| 国产美女一区二区三区| 欧美国产综合一区二区| 青花影视在线观看免费高清| 国产91对白在线观看九色| 国产精品久久久久影院老司 | 国产精品福利在线播放| 国产盗摄一区二区三区在线| 成人免费看片app下载| 亚洲欧美日韩小说| 欧美日韩一区三区四区| 男人的天堂影院| 美国欧美日韩国产在线播放| 亚洲精品一区二区三区精华液| 亚洲一区 欧美| 成人动漫一区二区三区| 亚洲午夜激情av| 欧美大胆一级视频| 亚洲色图27p| 亚洲成人av免费观看| 日韩和欧美一区二区| www国产成人| 精品国产乱码久久久久久鸭王1| 99精品国产热久久91蜜凸| 亚洲一区av在线| 欧美成人精品高清在线播放| 欧日韩不卡视频| 91视频一区二区三区| 日韩av电影天堂| 国产日韩欧美精品一区| 日本福利一区二区| 熟女人妻在线视频| 国产suv精品一区二区6| 亚洲国产日韩精品| 久久亚洲一区二区三区四区| 色婷婷综合五月| 黄色在线免费播放| 国产一区二区三区综合| 亚洲女性喷水在线观看一区| 日韩欧美在线一区二区三区| 97精品在线播放| 人妻 日韩 欧美 综合 制服| 六月婷婷色综合| 亚洲欧美日韩人成在线播放| 日韩欧美在线一区二区三区| 国产黄色的视频| 欧美成人三级伦在线观看| 国产精品中文欧美| 五月天久久比比资源色| 日本一区二区综合亚洲| 欧美精选在线播放| 国产麻豆a毛片| 国产又粗又猛又色| 成人18视频在线播放| 日本中文字幕不卡| 网爆门在线观看| www.com日本| 成人午夜电影小说| 蜜臀久久99精品久久久久宅男| 国产精品成人免费精品自在线观看| 91精品国产综合久久精品| 日本一二三区在线观看| asian性开放少妇pics|