亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

關(guān)于python的繼承的一個(gè)疑問(wèn)

瀏覽:149日期:2022-08-18 14:17:38

問(wèn)題描述

關(guān)于python的繼承的一個(gè)疑問(wèn)

如圖所示,B 類(lèi)繼承了 A 類(lèi);

當(dāng)實(shí)例化對(duì)象時(shí),B 類(lèi)中沒(méi)有構(gòu)造函數(shù), 應(yīng)該調(diào)用父類(lèi)的構(gòu)造函數(shù) __init__

但是里邊的 self.__pirv() 為啥調(diào)用到父類(lèi) A 的 __priv, 而 self.pub() 又調(diào)到 B 中的 pub

求解?

問(wèn)題解答

回答1:

在Python從__開(kāi)始的方法名稱(chēng)不是private,__的意思就讓Python做name mangling,name mangling的結(jié)果就是_A__priv。這樣的方法你應(yīng)該不要overwrite。如果你想讓子類(lèi)overwrite一個(gè)方法你只用_,不用__

回答2:

想了一下這個(gè)問(wèn)題,我是這樣理解的:

class A(object): def __init__(self):self.__priv() # _A__priv()self.pub() def __priv(self):print('private A') def pub(self):print('public A')class B(A): def __init__(self):self.__priv() # 調(diào)用_B__priv()對(duì)比super(B, self).__init__() # 在這里顯式調(diào)用父類(lèi)的`__init__()`方法 def __priv(self):print('private B') def pub(self):print('public B')if __name__ == ’__main__’: b = B()

在子類(lèi)的實(shí)例調(diào)用__init__()方法時(shí),從子類(lèi)B本身中查找pub()方法,顯然是存在的,因此會(huì)調(diào)用B類(lèi)自身的pub()方法;然而在調(diào)用__priv()方法時(shí),由于Python對(duì)私有成員進(jìn)行了名稱(chēng)改編,你實(shí)際調(diào)用的是_A__priv()方法,而B(niǎo)類(lèi)中并沒(méi)有這個(gè)方法,有的只有_B__priv(),因此調(diào)用父類(lèi)A中的_A__priv(),于是產(chǎn)生了這樣的結(jié)果。這是我個(gè)人的理解,如果有誤歡迎指正,謝謝。

回答3:

關(guān)於問(wèn)題本身, @Xavier 和 @Christoph 已經(jīng)有詳細(xì)的說(shuō)明了

如果你還不明白可以試著這樣做:

原本的代碼:

class A: def __init__(self):self.__priv() # 等等改成 self._A__priv()self.public() def __priv(self): # 等等改成 def _A__priv(self):print(’private of A’) def public(self):print(’public of A’)class B(A): def __priv(self): # 等等改成 self._B__priv(self):print(’private of B’) def public(self):print(’public of B’)b = B()

自行手動(dòng)進(jìn)行 name mangling:

class A: def __init__(self):self._A__priv()self.public() def _A__priv(self):print(’private of A’) def public(self):print(’public of A’)class B(A): def _B__priv(self):print(’private of B’) def public(self):print(’public of B’)b = B()

B 在這裡繼承了 A 的所有屬性包含:

__init__

_A__priv

public

而 B 自己定義了:

_B__priv

public (此處覆寫(xiě)了 A 的 public)

所以最後你會(huì)看到 dir(b) 裡面有:

__init__ (從 A 繼承的)

_A__priv (從 A 繼承的)

_B__priv (自己定義的)

public (自己定義的)

最後當(dāng) __init__ 被呼叫時(shí), 會(huì)調(diào)用 _A__priv, 而 B 裡面的確有這個(gè)方法

囉唆補(bǔ)充一下, Python 本身並沒(méi)有真正的 private 機(jī)制, 因?yàn)榱私?name mangling 的人就能對(duì)以雙底線開(kāi)頭的屬性做存取, 比如說(shuō)我可以很輕易地寫(xiě)出:

a = A()a._A__priv() # 防都防不住

簡(jiǎn)單來(lái)說(shuō)這個(gè)機(jī)制是個(gè):

防呆 的機(jī)制, 不是個(gè) 防小人 的機(jī)制,

防止意外 存取的機(jī)制, 不是個(gè)防止 刻意存取 的機(jī)制

但是這個(gè)機(jī)制並非所有人都覺(jué)得好(個(gè)人就不喜歡, 使用雙底線開(kāi)頭命名既麻煩也沒(méi)太多實(shí)際的幫助), 所以你可以在很多的 python 代碼中發(fā)現(xiàn): 大家比較常使用以 單個(gè)底線 開(kāi)頭的保護(hù)方式, 這種做法是個(gè)公認(rèn)的慣例(註1), 對(duì)於稍有經(jīng)驗(yàn)的程序員來(lái)說(shuō)足以防呆, 且不會(huì)有任何額外的效果和意外的狀況發(fā)生

Ian Bicking 有一段話是這樣說(shuō)的 (Ian Bicking 是 Python 大神, 這段話我是在 Luciano Ramalho 的的 Fluent Python 中看到的):

永遠(yuǎn)不要在前面使用兩個(gè)底線. 這是很讓人生氣的自私行為, 如果你不希望造成名稱(chēng)衝突(註2), 可以明確地重整名稱(chēng)(例如: _MyThing_blahblah). 實(shí)質(zhì)上這與使用雙底線是同一件事情, 不過(guò)他是公開(kāi)的, 雙底線是私下的行為.

所以我的建議是, 使用 _priv 會(huì)是更好的選擇.

註1: 以單底線開(kāi)頭的屬性不會(huì)具有任何特殊的性質(zhì), 他僅僅是依靠 Python 程序員的共識(shí)而產(chǎn)生的具有象徵意義的符號(hào)性手法, 就好像有些語(yǔ)言會(huì)使用 const 來(lái)標(biāo)明常量, 而我們也可以僅依賴(lài) 常量使用大寫(xiě)命名 的共識(shí)來(lái)避免意外的狀況發(fā)生

註2: 之所以想要以 private 性質(zhì)來(lái)保護(hù)屬性, 最常見(jiàn)的就是因?yàn)槊Q(chēng)衝突引起的意外存取

我回答過(guò)的問(wèn)題: Python-QA

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 精品一二区 | 国产在线看不卡一区二区 | 亚洲欧美日本国产综合在线 | 91精品在线免费观看 | 久久九九国产 | 午夜国产在线观看 | 久久亚洲综合色 | 亚洲欧美日韩综合在线播放 | 韩日一级视频 | 色综合天天综合高清影视 | 欧美另类老人xxxx | 99青草青草久热精品视频 | 免费日韩在线 | a高清免费毛片久久 | 国产九色在线 | 黄色在线 | 欧美一级在线全免费 | 99久久国产综合色 | 未满十八18周岁禁止免费国产 | 婷婷六月久久综合丁香可观看 | 国产精品高清一区二区 | 欧美黑人特大巨黑吊 | 国内自拍网站 | 日韩妞干网 | 成人毛片一区二区三区 | 久久www免费人成_看片高清 | 色网址在线 | 久久国产成人精品国产成人亚洲 | 国产在线播放成人免费 | 欧美亚洲日本国产 | 亚洲欧美高清 | 亚洲国产韩国一区二区 | 岛国片欧美一级毛片 | 国产精品人成在线播放新网站 | 久久久精品一级二级三级 | 国产日比 | 免费看三级全黄 | 黄色三级网站免费 | 国产激情一区二区三区成人91 | 欧美大黄特黄一级毛片 | a级在线播放 |