Python類中屬性的訪問權限分爲:public
和private
兩種,然後對於C++類來說有:public、protected
和private
三種類型。
class MyObject(object):
def __init__(slef):
self.public_field = 5
self.__private_field = 10
def get_private_field(self):
return self.__private_field
if __name__=='__main__':
foo = MyObject()
assert foo.public_field == 5
其中,以兩個下劃線開頭的變量爲私有屬性,__private_field
在類外面直接訪問private
字段會引發異常。
foo.__private_field
>>> AttributeError:'MyObject' object has no attribute '__private_field'
同時,子類也無法獲取父類的私有屬性。
class MyParentObject(object):
def __init__(self):
self.__private_field = 5
class MyChildObject(MyParentObject):
def __init__(self):
super().__init__()
def get_private_field(self):
return self.__private_field
if __name__ == '__main__':
foo = MyChildObject()
print(foo.get_private_field)
Python無法訪問私有屬性,只是因爲Python對私有屬性的名稱做了一些簡單的變換,以保證private
字段的私密性。當編譯器看到MyParentObject
中定義了__private_field
屬性時,會將其變爲:_MyParentObject__private_field
,而在MyChildObject
看到__private_field
私有屬性時,會將其變爲_MyChildObject__private_field
。
因此,從上面可以看出子類之所以無法訪問父類私有變量,其實是變換後的屬性名稱與待訪問的屬性名不一樣罷了。
瞭解了這套機制後,可以任意的訪問類的私有屬性。
class MyObject(object):
def __init__(slef):
self.public_field = 5
self.__private_field = 10
def get_private_field(self):
return self.__private_field
if __name__=='__main__':
foo = MyObject()
assert foo.public_field == 5
print(foo._MyObject__private_field)
因此,在實際開發中,爲了儘量減少無意間訪問內部屬性帶來的意外,應該按照《Python風格指南》的建議,按照如下規則:以單個下劃線開頭的字段視爲protected
字段,同時應該在類文檔中說明這些保護字段的含義。