W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
你想封裝類的實例上面的“私有”數(shù)據(jù),但是Python語言并沒有訪問控制。
Python程序員不去依賴語言特性去封裝數(shù)據(jù),而是通過遵循一定的屬性和方法命名規(guī)約來達到這個效果。第一個約定是任何以單下劃線_開頭的名字都應該是內(nèi)部實現(xiàn)。比如:
class A:
def __init__(self):
self._internal = 0 # An internal attribute
self.public = 1 # A public attribute
def public_method(self):
'''
A public method
'''
pass
def _internal_method(self):
pass
Python并不會真的阻止別人訪問內(nèi)部名稱。但是如果你這么做肯定是不好的,可能會導致脆弱的代碼。同時還要注意到,使用下劃線開頭的約定同樣適用于模塊名和模塊級別函數(shù)。例如,如果你看到某個模塊名以單下劃線開頭(比如_socket),那它就是內(nèi)部實現(xiàn)。類似的,模塊級別函數(shù)比如 sys._getframe()
在使用的時候就得加倍小心了。
你還可能會遇到在類定義中使用兩個下劃線(__)開頭的命名。比如:
class B:
def __init__(self):
self.__private = 0
def __private_method(self):
pass
def public_method(self):
pass
self.__private_method()
使用雙下劃線開始會導致訪問名稱變成其他形式。比如,在前面的類B中,私有屬性會被分別重命名為 _B__private
和 _B__private_method
。這時候你可能會問這樣重命名的目的是什么,答案就是繼承——這種屬性通過繼承是無法被覆蓋的。比如:
class C(B):
def __init__(self):
super().__init__()
self.__private = 1 # Does not override B.__private
# Does not override B.__private_method()
def __private_method(self):
pass
這里,私有名稱 __private
和 __private_method
被重命名為 _C__private
和 _C__private_method
,這個跟父類B中的名稱是完全不同的。
上面提到有兩種不同的編碼約定(單下劃線和雙下劃線)來命名私有屬性,那么問題就來了:到底哪種方式好呢?大多數(shù)而言,你應該讓你的非公共名稱以單下劃線開頭。但是,如果你清楚你的代碼會涉及到子類,并且有些內(nèi)部屬性應該在子類中隱藏起來,那么才考慮使用雙下劃線方案。
還有一點要注意的是,有時候你定義的一個變量和某個保留關鍵字沖突,這時候可以使用單下劃線作為后綴,例如:
lambda_ = 2.0 # Trailing _ to avoid clash with lambda keyword
這里我們并不使用單下劃線前綴的原因是它避免誤解它的使用初衷(如使用單下劃線前綴的目的是為了防止命名沖突而不是指明這個屬性是私有的)。通過使用單下劃線后綴可以解決這個問題。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: