上一節我們介紹了,Class內部可以有屬性和方法,外部代碼通過直接調用實例的方法來操作數據,這樣就可以隱藏內部的邏輯實現;同時,外部代碼還是可以自由的修改實例的屬性和增加方法。
但是有時候,我們不想這樣呢?即不讓內部屬性被外部訪問。
可以在屬性的名稱前面加上兩個下划線__。如果一個變量以__開頭,就變成了一個私有變量private,只有內部可以訪問。
修改一下Student類:
class Student(object): def __init__(self,name,score): self.__name = name self.__score = score def print_stu(self): print('姓名:%s,成績%s'%(self.__name,self.__score))
現在已經無法從外部訪問實例.__name和實例.__score了:
>>> wc = Student('wc',66) >>> wc.__name Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Student' object has no attribute '__name'
如果我們的確需要從外部獲取name和score呢?通常的做法,是給類增加get的方法:
class Student(object): def __init__(self,name,score): self.__name = name self.__score = score def print_stu(self): print('姓名:%s,成績:%s'%(self.__name,self.__score)) def getName(self): return self.__name def getScore(self): return self.__score
同理,我們還可以給該類增加setName的方法,使得外部代碼可以先修改name。同時,我們還可以在這些方法中增加健壯性檢查,避免傳入錯誤的參數。
注意:python中,變量名類似於__xxx__的,是特殊變量,是可以直接訪問的,並不是私有變量。有些時候,可能會出現_name這樣的變量,這樣的變量也是可以訪問的,但是約定俗成:可以被訪問,但是最好不要隨意訪問。
問題又來了,類似於__xxx雙下划綫開頭的變量,真的不能被外部訪問嗎?其實也可以訪問。python解釋器對外會把__name變量變成_Student__name,你按照實例.__name當然訪問不了了,這時可以使用實例._Student__name來訪問__name變量:
>>> wc._Student__name 'wc'
但是,不同版本的python解釋器可能會把__name改成不同的變量名,強烈建議你程序不能這么干。
再來看一個例子:
>>> ly = Student('ly',55) >>> ly.getName() 'ly' >>> ly.__name = 'haha' >>> ly.__name 'haha'
表面上,外部代碼好像成功的設置了__name變量,其實不是的。這里的__name變量和class內部的__name變量並不是一個變量。驗證:
>>> ly.getName() 'ly'