成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

既是爸爸又是爺爺?Python 多繼承中的一個詭異現象

開發 后端
我們知道,在面向對象編程里面,繼承是一個很重要的概念。子類可以使用父類的方法和屬性。

我們知道,在面向對象編程里面,繼承是一個很重要的概念。子類可以使用父類的方法和屬性。例如下面這段代碼:

  1. class Father: 
  2.     def __init__(self): 
  3.         self.address = '上海' 
  4.  
  5.     def say(self): 
  6.         print('我是爸爸') 
  7.  
  8. class Son(Father): 
  9.     def __init__(self): 
  10.         super().__init__() 
  11.  
  12.     def say(self): 
  13.         print('我是兒子') 
  14.  
  15. son = Son() 
  16. print(son.address) 

運行效果如下圖所示:

從圖中可以看到,子類并沒有self.address這個屬性,但是當我們直接打印的時候,并不會報錯,它會自動使用父類的address屬性。

顯然,如果一個屬性,子類也沒有,父類也沒有,那肯定會報錯,如下圖所示:

我們也知道,Python 是支持多繼承的,一個子類可以有多個父類。那么,大家請看下面這段代碼:

  1. class GrandFather: 
  2.     def __init__(self): 
  3.         self.address = '上海' 
  4.  
  5.     def say(self): 
  6.         print('我是爸爸') 
  7.  
  8. class Father: 
  9.     def __init__(self): 
  10.         self.age = 100 
  11.      
  12.     def where(self): 
  13.         print('我現在住在:', self.address) 
  14.  
  15. class Son(GrandFather, Father): 
  16.     def __init__(self): 
  17.         super().__init__() 
  18.  
  19.     def say(self): 
  20.         print('我是兒子') 
  21.  
  22. son = Son() 
  23. son.where() 

運行效果如下圖所示:

大家仔細觀察,會發現這段代碼有點奇怪。我調用的是son.where()方法,由于Son類沒有這個方法,于是它會去它的兩個父類里面找。于是在Father這個父類里面找到了。于是執行Father里面的where()方法,目前為止沒有問題。

但接下來就不對了,.where()方法里面,調用了self.address屬性??蓡栴}是Father這個類它并沒有.address屬性啊!而且Father也沒有父類,那么這個.address屬性是從哪里來的?

難道說,在開發者不知道的隱秘的角落里面,GrandFather 類悄悄成為了Father的父類?這樣一來,GrandFather豈不是又是 C 的父類,又是 C 的父類的父類?GrandFather既是爸爸又是爺爺?

實際上,并不存在這么混亂的關系。要解釋這個現象,我們就要從self這個東西說起。

我們知道,類的屬性都是以self開頭,方法的第一個參數也是self。那么這個 self 到底是什么東西?我們用一段小代碼來看看它是什么東西:

  1. class A: 
  2.     def get_self(self): 
  3.         return self 
  4.  
  5. test = A() 
  6. what_is_self = test.get_self() 
  7.  
  8. test is what_is_self 

運行效果如下圖所示:

從圖里面可以看到,self實際上就是這個類的實例。我們再來看有繼承的情況:

  1. class A: 
  2.     def get_self(self): 
  3.         return self 
  4.  
  5. class B(A): 
  6.     def __init__(self): 
  7.         ... 
  8.  
  9. test = B() 
  10. what_is_self = test.get_self() 
  11.  
  12. print(what_is_self) 

從圖中可以看到,雖然我在 A 類的.get_self()方法中返回了self,但這個self實際上是 B 類的實例。因為我自始至終就只初始化了 B 類,并沒有初始化 A 類。A 雖然是 B 類的父類。但父類的 self 都會變成子類的實例。

明白這一點以后,前面的問題就很好解釋了,我們多打印一些信息:

大家注意畫紅線的地方,self始終都是Son類的實例。所以,一開始初始化.address的時候,就是初始化的Son的實例的.address屬性。后面在.where里面調用.address的時候,也是讀取的Son的實例的.address屬性。所以,并不存在Father類去讀GrandFather類的情況。自始至終,都是Son類的實例在進行各種操作。

所以,在這個例子里面,當使用了繼承以后,所有父類的屬性和方法,子類如果有相同的名字,那么以子類的為準。如果子類沒有定義,那么父類的屬性和方法,其實都會跑到子類里面去。所有看起來是父類進行的操作,其實都是子類在進行。上面的代碼,甚至可以近似等價于:

由于say方法在子類中有了定義,所以子類覆蓋父類。以子類的say方法為準。where和address由于子類沒有定義,所以Father類的where方法和GrandFather里面的address屬性,都會直接跑到子類里面。

 

責任編輯:趙寧寧 來源: 未聞Code
相關推薦

2023-02-23 08:02:19

PulsarJava

2020-12-31 11:01:26

互聯網數據技術

2022-06-15 08:14:40

Go線程遞歸

2013-12-05 10:50:13

2024-06-28 08:28:43

反序列化filterJson

2022-11-28 08:37:23

MQ集群線程棧

2021-04-30 07:09:48

SQLP0事故

2016-11-03 08:57:02

javascriptjquerynode.js

2017-06-01 23:25:50

網絡安全法網絡安全信息安全

2009-07-14 17:36:28

Jython的繼承

2019-12-30 14:34:33

NumpyPython數據科學

2024-01-22 13:59:00

模型訓練

2011-08-17 10:28:53

多對多查詢SQL Server

2022-04-14 20:43:24

JavaScript原型鏈

2011-04-11 09:53:06

Oracle

2014-05-26 09:13:46

DockerPython

2015-06-02 04:13:23

Python乒乓球類游戲

2018-04-20 09:24:08

Hbase存儲注意點

2009-05-13 11:50:17

C#多繼承接口

2013-05-07 13:46:31

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: www.天天操.com | 精品国产区 | 天天操人人干 | 一区二区三区在线免费观看视频 | 欧美综合在线视频 | 国产精品久久久爽爽爽麻豆色哟哟 | 美女精品一区 | 色就是色欧美 | 国产精品免费一区二区三区四区 | 人人做人人澡人人爽欧美 | 亚洲欧美自拍偷拍视频 | 久久视频免费观看 | 成人免费视频在线观看 | 国产一区2区 | 成人在线播放网址 | 欧美国产日韩成人 | 狠狠伊人| 成人黄色电影在线播放 | 日韩爱爱网站 | 亚洲一二三区免费 | 久久1区 | 精品九九 | 免费成人在线网 | 激情国产在线 | 自拍偷拍中文字幕 | 午夜性视频 | 国产日韩欧美综合 | 欧美成年黄网站色视频 | 日本涩涩视频 | 久久精品亚洲一区二区三区浴池 | 五月激情婷婷在线 | av在线免费网| 久色| 成人一级毛片 | 国产精品久久一区二区三区 | 91精品国产乱码久久久久久 | av资源在线看 | 国产激情毛片 | 中文字字幕一区二区三区四区五区 | 欧美日韩精品免费 | 午夜精品久久久久久久99黑人 |