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()
自行手動進行 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 (此處覆寫了 A 的 public (此處覆寫了 A 的
)
dir(b)所以最後你會看到
裡面有:
__init__ (從 A
(從 A 繼承的)
_A__priv (從 A
(從 A 繼承的)
_B__priv
(自己定義的)
public
(自己定義的)
__init__ 被呼叫時, 會調用 _A__priv, 而 B最後當
被呼叫時, 會呼叫 , 而
裡面的確有這個方法
囉唆補充一下, Python 本身並沒有真正的 private 機制, 因為了解 name mangling 的人就能對以雙底線開頭的屬性做訪問, 比如說我可以很輕易地寫出:
在Python從__開始的方法名稱不是private,__的意思就讓Python做name mangling,name mangling的結果就是_A__priv。這樣的方法你應該不要overwrite。如果你想讓子類overwrite一個方法你只用_,不用__
想了一下這個問題,我是這樣理解的:
在子類別的實例呼叫
__init__()
方法时,从子类B
本身中查找pub()
方法,显然是存在的,因此会调用B
类自身的pub()
方法;然而在调用__priv()
方法时,由于Python对私有成员进行了名称改编,你实际调用的是_A__priv()
方法,而B
类中并没有这个方法,有的只有_B__priv()
,因此调用父类A
中的_A__priv()
,於是產生了這樣的結果。這是我個人的理解,如果有誤歡迎指正,謝謝。關於問題本身, @Xavier 和 @Christoph 已經有詳細的說明了
如果你還不明白可以試著這樣做:
原本的程式碼:
自行手動進行 name mangling:
B
在這裡繼承了A
的所有屬性都包含:__init__
_A__priv
public
而
B
自己定義了:_B__priv
)public
(此處覆寫了A
的public
(此處覆寫了A
的dir(b)
所以最後你會看到
(從__init__
(從A
A
繼承的)
(從_A__priv
(從A
A
繼承的)
(自己定義的)_B__priv
(自己定義的)public
__init__
被呼叫時, 會調用_A__priv
, 而B
最後當, 而
裡面的確有這個方法
防呆
的機制, 不是個防止意外
訪問的機制, 不是個防止單個底線
開頭的保護方式, 這種做法是個公認的慣例(注1), 對於稍有經驗的程式設計師來說足以防呆, 且不會有任何額外的效果和意外的狀況發生永遠不要在前面使用兩個底線. 這是很讓人生氣的自私行為, 如果你不希望造成名稱衝突(註2), 可以明確地重整名稱(例如: _MyThing_blahblah). 實質上這與使用雙底線是同一件事, 不過他是公開的, 雙底線是私下的行為.
_priv
所以我的建議是, 使用
會是更好的選擇.
來標明常量, 而我們也可以只依賴const
註1: 以單底線開頭的屬性不會具有任何特殊的性質, 他僅僅是依靠Python 程式設計師的共識而產生的具有像徵意義的符號性手法, 就好像有些語言會使用常數使用大寫命名
的共識來避免意外的狀況發生🎜 🎜註2: 之所以想要以 private 性質來保護屬性, 最常見的就是因為名稱衝突引起的意外訪問🎜我回答過的問題: Python-QA