第27條 多使用public屬性,少用private屬性

Python類中屬性的訪問權限分爲:publicprivate兩種,然後對於C++類來說有:public、protectedprivate三種類型。

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字段,同時應該在類文檔中說明這些保護字段的含義。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章