欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python中的繼承機制super()函數詳解

 更新時間:2023年08月24日 14:14:43   作者:goodxin_ie  
這篇文章主要介紹了python中的繼承機制super()函數詳解,super 是用來解決多重繼承問題的,直接用類名調用父類方法在使用單繼承的時候沒問題,但是如果使用多繼承,會涉及到查找順序、重復調用等問題,需要的朋友可以參考下

前言

super 是用來解決多重繼承問題的,直接用類名調用父類方法在使用單繼承的時候沒問題

但是如果使用多繼承,會涉及到查找順序(MRO)、重復調用(鉆石繼承)等種種問題。

一、super用法

我們先簡單的理解為super().xx相當于調用了父類中的xx方法(實際上在單繼承中是這樣,多繼承中有點區(qū)別)。

時候會看到像下面這樣直接調用父類的一個方法:

class Base:
    def __init__(self):
        print('Base.__init__')
class A(Base):
    def __init__(self):
        Base.__init__(self)
        print('A.__init__')

盡管對于大部分代碼而言這么做沒什么問題,但是在更復雜的涉及到多繼承的代碼中就有可能導致很奇怪的問題發(fā)生。

比如,考慮如下的情況:

class Base:
    def __init__(self):
        print('Base.__init__')
class A(Base):
    def __init__(self):
        Base.__init__(self)
        print('A.__init__')
class B(Base):
    def __init__(self):
        Base.__init__(self)
        print('B.__init__')
class C(A,B):
    def __init__(self):
        A.__init__(self)
        B.__init__(self)
        print('C.__init__')
c = C()

如果你運行這段代碼就會發(fā)現(xiàn) Base.__init__() 被調用兩次,如下所示:

 
Base.__init__
A.__init__
Base.__init__
B.__init__
C.__init__

但是當我們在代碼中換成使用 super() ,結果就很完美了:

class Base:
    def __init__(self):
        print('Base.__init__')
class A(Base):
    def __init__(self):
        super().__init__()
        print('A.__init__')
class B(Base):
    def __init__(self):
        super().__init__()
        print('B.__init__')
class C(A,B):
    def __init__(self):
        super().__init__()  # Only one call to super() here
        print('C.__init__')

運行這個新版本后,你會發(fā)現(xiàn)每個 __init__() 方法只會被調用一次了:

Base.__init__
B.__init__
A.__init__
C.__init__

二、super的本質

先說說python中如何實現(xiàn)繼承---------對于你定義的每一個類,Python會計算出一個所謂的方法解析順序(MRO)列表。 這個MRO列表就是一個簡單的所有基類的線性順序表。為了實現(xiàn)繼承,Python會在MRO列表上從左到右開始查找基類,直到找到第一個匹配這個屬性的類為止。

而這個MRO列表的構造是通過一個C3線性化算法來實現(xiàn)的。 我們不去深究這個算法的數學原理,它實際上就是合并所有父類的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]

我們來看一個例子,猜猜下面的輸出會是什么呢:

class A():
    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()

直接看結果:

很多人將super簡單的理解為調用父類中的方法,可能認為應該是D調用B和C,由于B在左邊,按順序先調用B,B油調用A,完成之后輪到D調用C,C調用A.輸出變成下面這樣:

Enter D
Enter B
Enter A
Leave B
Enter C
Enter A
Leave C
Leave D

但是根據我們上面說的super本質知道super 和父類其實沒有實質關聯(lián),我們就不難理解為什么 enter B 下一句是 enter C 而不是 enter A了(如果認為 super 代表“調用父類的方法”,會想當然的認為下一句應該是enter A)。流程如下,在 B 的 __init__ 函數中:

super(B,self).__init__() 首先獲取self.__class__.__mro__,但是這里的self是D的實例,而不是B的。

(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

然后,通過 B 來定位 MRO 中的 index,并找到下一個。

顯然 B 的下一個是 C。于是,我們調用 C 的 __init__,打出 enter C。

當你使用super()函數時,Python會在MRO列表上繼續(xù)搜索下一個類。

只要每個重定義的方法統(tǒng)一使用super()并只調用它一次, 那么控制流最終會遍歷完整個MRO列表,每個方法也只會被調用一次。

到此這篇關于python中的繼承機制super()函數詳解的文章就介紹到這了,更多相關python繼承super()函數內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Python制作腳本幫女朋友搶購清空購物車

    Python制作腳本幫女朋友搶購清空購物車

    這篇文章主要介紹了Python制作的搶購清空購物車的腳本,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08
  • python實現(xiàn)圖像拼接功能

    python實現(xiàn)圖像拼接功能

    這篇文章主要為大家詳細介紹了python實現(xiàn)圖像拼接功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • Python實現(xiàn)批量修改文件日期

    Python實現(xiàn)批量修改文件日期

    在日常工作和學習中,我們經常需要修改文件的創(chuàng)建或修改日期,本文將介紹如何使用Python編寫一個批量文件日期修改器,有需要的可以參考下
    2025-03-03
  • Python的迭代器和生成器使用實例

    Python的迭代器和生成器使用實例

    這篇文章主要介紹了Python的迭代器和生成器使用實例,本文講解了迭代器的next方法、__iter__方法和實例以及生成器的代碼實例,需要的朋友可以參考下
    2015-01-01
  • django orm模糊查詢、正則匹配多個值方式

    django orm模糊查詢、正則匹配多個值方式

    這篇文章主要介紹了django orm模糊查詢、正則匹配多個值方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 解決python 3 urllib 沒有 urlencode 屬性的問題

    解決python 3 urllib 沒有 urlencode 屬性的問題

    今天小編就為大家分享一篇解決python 3 urllib 沒有 urlencode 屬性的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08
  • Python讀取中文路徑出現(xiàn)亂碼的問題解決

    Python讀取中文路徑出現(xiàn)亂碼的問題解決

    本文主要介紹了Python讀取中文路徑出現(xiàn)亂碼的問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-06-06
  • python 如何把docker-compose.yaml導入到數據庫相關條目里

    python 如何把docker-compose.yaml導入到數據庫相關條目里

    這篇文章主要介紹了python 如何把docker-compose.yaml導入到數據庫相關條目里?下面小編就為大家介紹一下實現(xiàn)方式,一起跟隨小編過來看看吧
    2021-01-01
  • 介紹Python中的__future__模塊

    介紹Python中的__future__模塊

    這篇文章主要介紹了介紹Python中的__future__模塊,__future__模塊使得在Python2.x的版本下能夠兼容更多的Python3.x的特性,需要的朋友可以參考下
    2015-04-04
  • 基于Tensorflow搭建一個神經網絡的實現(xiàn)

    基于Tensorflow搭建一個神經網絡的實現(xiàn)

    神經網絡可能會讓人感到恐懼,特別是對于新手機器學習的人來說。這篇文章主要介紹了基于Tensorflow搭建一個神經網絡的實現(xiàn),從入門開始,感興趣的可以了解一下
    2021-05-05

最新評論