日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多继承以及MRO顺序【super().的使用】

發布時間:2023/12/20 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多继承以及MRO顺序【super().的使用】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

多繼承以及MRO順序

1. 單獨調用父類的方法

# coding=utf-8print("******多繼承使用類名.__init__ 發生的狀態******") class Parent(object):def __init__(self, name):print('parent的init開始被調用')self.name = nameprint('parent的init結束被調用')class Son1(Parent):def __init__(self, name, age):print('Son1的init開始被調用')self.age = ageParent.__init__(self, name)print('Son1的init結束被調用')class Son2(Parent):def __init__(self, name, gender):print('Son2的init開始被調用')self.gender = genderParent.__init__(self, name)print('Son2的init結束被調用')class Grandson(Son1, Son2):def __init__(self, name, age, gender):print('Grandson的init開始被調用')Son1.__init__(self, name, age) # 單獨調用父類的初始化方法Son2.__init__(self, name, gender)print('Grandson的init結束被調用')gs = Grandson('grandson', 12, '男') print('姓名:', gs.name) print('年齡:', gs.age) print('性別:', gs.gender)print("******多繼承使用類名.__init__ 發生的狀態******\n\n")

運行結果:

******多繼承使用類名.__init__ 發生的狀態****** Grandson的init開始被調用 Son1的init開始被調用 parent的init開始被調用 parent的init結束被調用 Son1的init結束被調用 Son2的init開始被調用 parent的init開始被調用 parent的init結束被調用 Son2的init結束被調用 Grandson的init結束被調用 姓名: grandson 年齡: 12 性別: 男 ******多繼承使用類名.__init__ 發生的狀態******

2. 多繼承中super調用有所父類的被重寫的方法

print("******多繼承使用super().__init__ 發生的狀態******") class Parent(object):def __init__(self, name, *args, **kwargs): # 為避免多繼承報錯,使用不定長參數,接受參數print('parent的init開始被調用')self.name = nameprint('parent的init結束被調用')class Son1(Parent):def __init__(self, name, age, *args, **kwargs): # 為避免多繼承報錯,使用不定長參數,接受參數print('Son1的init開始被調用')self.age = agesuper().__init__(name, *args, **kwargs) # 為避免多繼承報錯,使用不定長參數,接受參數print('Son1的init結束被調用')class Son2(Parent):def __init__(self, name, gender, *args, **kwargs): # 為避免多繼承報錯,使用不定長參數,接受參數print('Son2的init開始被調用')self.gender = gendersuper().__init__(name, *args, **kwargs) # 為避免多繼承報錯,使用不定長參數,接受參數print('Son2的init結束被調用')class Grandson(Son1, Son2):def __init__(self, name, age, gender):print('Grandson的init開始被調用')# 多繼承時,相對于使用類名.__init__方法,要把每個父類全部寫一遍# 而super只用一句話,執行了全部父類的方法,這也是為何多繼承需要全部傳參的一個原因# super(Grandson, self).__init__(name, age, gender)super().__init__(name, age, gender)print('Grandson的init結束被調用')print(Grandson.__mro__)gs = Grandson('grandson', 12, '男') print('姓名:', gs.name) print('年齡:', gs.age) print('性別:', gs.gender) print("******多繼承使用super().__init__ 發生的狀態******\n\n")

運行結果:

******多繼承使用super().__init__ 發生的狀態****** (<class '__main__.Grandson'>, <class '__main__.Son1'>, <class '__main__.Son2'>, <class '__main__.Parent'>, <class 'object'>) Grandson的init開始被調用 Son1的init開始被調用 Son2的init開始被調用 parent的init開始被調用 parent的init結束被調用 Son2的init結束被調用 Son1的init結束被調用 Grandson的init結束被調用 姓名: grandson 年齡: 12 性別: 男 ******多繼承使用super().__init__ 發生的狀態******

注意:

  • 以上2個代碼執行的結果不同
  • 如果2個子類中都繼承了父類,當在子類中通過父類名調用時,parent被執行了2次
  • 如果2個子類中都繼承了父類,當在子類中通過super調用時,parent被執行了1次
  • 3. 單繼承中super

    print("******單繼承使用super().__init__ 發生的狀態******") class Parent(object):def __init__(self, name):print('parent的init開始被調用')self.name = nameprint('parent的init結束被調用')class Son1(Parent):def __init__(self, name, age):print('Son1的init開始被調用')self.age = agesuper().__init__(name) # 單繼承不能提供全部參數print('Son1的init結束被調用')class Grandson(Son1):def __init__(self, name, age, gender):print('Grandson的init開始被調用')super().__init__(name, age) # 單繼承不能提供全部參數print('Grandson的init結束被調用')gs = Grandson('grandson', 12, '男') print('姓名:', gs.name) print('年齡:', gs.age) #print('性別:', gs.gender) print("******單繼承使用super().__init__ 發生的狀態******\n\n")

    總結

  • super().__init__相對于類名.__init__,在單繼承上用法基本無差
  • 但在多繼承上有區別,super方法能保證每個父類的方法只會執行一次,而使用類名的方法會導致方法被執行多次,具體看前面的輸出結果
  • 多繼承時,使用super方法,對父類的傳參數,應該是由于python中super的算法導致的原因,必須把參數全部傳遞,否則會報錯
  • 單繼承時,使用super方法,則不能全部傳遞,只能傳父類方法所需的參數,否則會報錯
  • 多繼承時,相對于使用類名.__init__方法,要把每個父類全部寫一遍, 而使用super方法,只需寫一句話便執行了全部父類的方法,這也是為何多繼承需要全部傳參的一個原因
  • 小試牛刀(以下為面試題)

    以下的代碼的輸出將是什么? 說出你的答案并解釋。

    class Parent(object):x = 1class Child1(Parent):passclass Child2(Parent):passprint(Parent.x, Child1.x, Child2.x) Child1.x = 2 print(Parent.x, Child1.x, Child2.x) Parent.x = 3 print(Parent.x, Child1.x, Child2.x)

    答案, 以上代碼的輸出是:

    1 1 1 1 2 1 3 2 3

    使你困惑或是驚奇的是關于最后一行的輸出是 3 2 3 而不是 3 2 1。為什么改變了 Parent.x 的值還會改變 Child2.x 的值,但是同時 Child1.x 值卻沒有改變?

    這個答案的關鍵是,在 Python 中,類變量在內部是作為字典處理的。如果一個變量的名字沒有在當前類的字典中發現,將搜索祖先類(比如父類)直到被引用的變量名被找到(如果這個被引用的變量名既沒有在自己所在的類又沒有在祖先類中找到,會引發一個 AttributeError 異常 )。

    因此,在父類中設置 x = 1 會使得類變量 x 在引用該類和其任何子類中的值為 1。這就是因為第一個 print 語句的輸出是 1 1 1。

    隨后,如果任何它的子類重寫了該值(例如,我們執行語句 Child1.x = 2),然后,該值僅僅在子類中被改變。這就是為什么第二個 print 語句的輸出是 1 2 1。

    最后,如果該值在父類中被改變(例如,我們執行語句 Parent.x = 3),這個改變會影響到任何未重寫該值的子類當中的值(在這個示例中被影響的子類是 Child2)。這就是為什么第三個 print 輸出是 3 2 3。

    總結

    以上是生活随笔為你收集整理的多继承以及MRO顺序【super().的使用】的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。