多繼承以及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__ 發生的狀態******

注意:

  1. 以上2個代碼執行的結果不同
  2. 如果2個子類中都繼承了父類,當在子類中通過父類名調用時,parent被執行了2次
  3. 如果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")

總結

  1. super().__init__相對于類名.__init__,在單繼承上用法基本無差
  2. 但在多繼承上有區別,super方法能保證每個父類的方法只會執行一次,而使用類名的方法會導致方法被執行多次,具體看前面的輸出結果
  3. 多繼承時,使用super方法,對父類的傳參數,應該是由于python中super的算法導致的原因,必須把參數全部傳遞,否則會報錯
  4. 單繼承時,使用super方法,則不能全部傳遞,只能傳父類方法所需的參數,否則會報錯
  5. 多繼承時,相對于使用類名.__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。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/456840.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/456840.shtml
英文地址,請注明出處:http://en.pswp.cn/news/456840.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

人工智能專業詞匯集

最近看到一篇關于AI專業詞匯總結的文章&#xff0c;感覺不錯&#xff0c;分享一下。 對應的詞匯項目地址為&#xff1a;https://github.com/jiqizhixin/Artificial-Intelligence-Terminology 本詞匯庫目前擁有的專業詞匯共計 500 個&#xff0c;主要為機器學習基礎概念和術語…

js 當前日期增加自然月

js 在日期不滿足的情況下就會自動加1個月&#xff0c;比如在當前時間為3月31號&#xff0c;傳入1&#xff0c;1兩個參數&#xff0c;預期結果為2月29日&#xff0c;但是結果輸出了3月2日。就是如果不滿就會溢出到下個月&#xff0c;后來看了api發現了setMonth有兩個方法&#x…

好雨云幫如何對接Git Server

前言 云幫目前支持對接GitLab、Gogs、Github,或者主流代碼托管平臺的公開項目&#xff0c;后期會考慮接入其他類型的Git服務。 私有云 GitLab是一個用于倉庫管理系統的開源項目&#xff0c;私有云服務里使用比較多的自建Git服務。 對接GitLab 通過應用市場進行安裝Gitlab 安裝G…

Python 生成requirement 使用requirements.txt

python項目中必須包含一個 requirements.txt 文件&#xff0c;用于記錄所有依賴包及其精確的版本號。以便新環境部署。requirements.txt可以通過pip命令自動生成和安裝生成requirements.txt文件 pip freeze > requirements.txt安裝requirements.txt依賴 pip install -r requ…

Source Insight上手教程

目錄Project的建立和工作區域同步查看定義查找引用查找調用Source Insight常用快捷鍵 目錄 最近剛參加工作&#xff0c;第一個任務就是查看項目的源碼&#xff0c;熟悉代碼結構。于是乎就簡單學習了Source Insight。在這里就轉載別人的文章當做自己的筆記&#xff0c;便于自己…

微信禁用右上角的分享按鈕,WeixinJSBridge API以及隱藏分享的子按鈕等菜單項

今天在做隱藏微信右上角的分享按鈕 百度查到的一串代碼&#xff0c;挺好用的 <!--禁用微信分享按鈕--><script>function onBridgeReady() {WeixinJSBridge.call(hideOptionMenu);}if (typeof WeixinJSBridge "undefined") {if (document.addEventListen…

python2.7無法使用pip(安裝easy_install)

python27和python36 共存時安裝pip方法&#xff0c;解決python27文件夾下沒有script文件方法 報錯&#xff1a; D:\PYTHON2.7>python ez_setup.py Downloading http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg Traceback (most recent call…

Codeforces 754E:Dasha and cyclic table

Codeforces 754E&#xff1a;Dasha and cyclic table 題目鏈接&#xff1a;http://codeforces.com/problemset/problem/754/E 題目大意&#xff1a;$A$矩陣&#xff08;$size(A)n \times m$&#xff0c;僅含a-z&#xff09;在整個平面做周期延拓&#xff0c;問$B$矩陣&#xff…

位運算中的左移和右移的計算詳解

最近在學習javaScrapt&#xff0c;在學到位運算符這部分的時候&#xff0c;突然發現看不懂書上的例子了。經過查找資料后&#xff0c;發現了一遍不錯的文章。分享一下&#xff1a; 正數的左移和右移 以3為例 3的二進制為 00000011 右移2位的時候將最右的11去掉左邊補00結果…

AC日記——字符串P型編碼 openjudge 1.7 31

31:字符串p型編碼 總時間限制: 1000ms內存限制: 65536kB描述給定一個完全由數字字符&#xff08;0,1,2,…,9&#xff09;構成的字符串str&#xff0c;請寫出str的p型編碼串。例如&#xff1a;字符串122344111可被描述為"1個1、2個2、1個3、2個4、3個1"&#xff0c;因…

javascript中的define用法

文章目錄1. AMD的由來2. AMD是什么3. AMD實例&#xff1a;如何定義一個模塊4. 匿名模塊5. 僅有一個參數的define6. Dojo中的AMD7. 結論最近由于工作需求只能快速學習JS&#xff0c;但在看代碼的時候發現許多東西都有疑問比如說代碼剛開始的define關鍵字的用法&#xff0c;剛好最…

解決:pip警告!DEPRECATION: The default format will switch to columns in the future.

pip警告&#xff01; DEPRECATION: The default format will switch to columns in the future. You can use --format(legacy|columns) (or define a format(legacy|columns) in your pip.conf under the [list] section) to disable this warning. pip升級到9.0.1后 查看pi…

PLSQL安裝配置

&#xff08;1&#xff09;解壓&#xff1a;plsql developer Oracle數據庫開發工具首先確保有oracle數據庫或者有oracle服務器&#xff0c;然后才能使用PLSQL Developer連接數據庫。&#xff08;2&#xff09;工具---首選項---連接----輸入OCI庫&#xff08;設置之后不用再裝or…

Mysql 學習筆記2

&#xff08;1&#xff09;MySQL查看表占用空間大小 //先進去MySQL自帶管理庫&#xff1a;information_schema //自己的數據庫&#xff1a;dbwww58com_kuchecarlib //自己的表&#xff1a;t_carmodelparamvalue mysql> use information_schema; Database changed mysql&g…

python程序打包為exe可執行文件

大家都知道&#xff0c;Python是一種腳本語言&#xff0c;也就是解釋型的語言&#xff0c;需要解釋器來進行解釋以后才可以執行&#xff0c;而Python源代碼需要在Python虛擬機上面運行&#xff0c;但是我們做好的程序&#xff0c;不可能給用戶使用的時候還讓他安裝一個Python環…

Backbone簡介

1. 前言 本文的目的&#xff0c;是幫助大家快速理解掌握Backbone的使用&#xff0c;但它并不是API&#xff0c;因此我不會將每一個方法都詳細地描述&#xff0c;但是我會告訴你如何學習它們。 這是一篇稍稍較長的技術文章&#xff0c;因為我想將我所了解的東西盡可能詳細地分享…

使用Android Studio搭建Android集成開發環境

一、Android Studio簡單介紹 2013年GoogleI/O大會首次發布了Android Studio IDE&#xff08;Android平臺集成開發環境&#xff09;。它基于Intellij IDEA開發環境&#xff0c;旨在取代Eclipse和ADT&#xff08;Android開發者工具&#xff09;為開發者提供更好的開發工具。既然G…

[Oracle]UNIX與Windows 2000上Oracle的差異(I)

作者&#xff1a;Ian Adam & David Stien, SAIC Ltd 日期&#xff1a;19-Dec-2003 出處&#xff1a;http://www.dbanotes.net翻譯&#xff1a;Fenng -----------------------------------------------------------------------------------------------------------------…

django2.x報錯No module named 'django.core.urlresolvers'

解決方法就是: from django.urls import reverse 最近從django1.9遷移到django2.0中出現一個意外的報錯&#xff1a; 這個報錯的原因在stack overflow上有很直接的解釋&#xff0c;但是百度上并沒有直接的答案。 簡單來說&#xff0c;原因就是&#xff1a;django2.0 把原來…

Underscore簡介

5. Underscore.js Underscore封裝了常用的JavaScript對象操作方法&#xff0c;用于提高開發效率。它本身與我們介紹的主題“Backbone”沒有半毛錢的關系&#xff0c;因此你可以完全不理會“Backbone”的概念來學習它&#xff0c;或將它單獨運用到任何一個頁面。&#xff08;另外…