封裝(Encapsulation)是對 object 的一種抽象,即將某些部分隱藏起來,在程序外部看不到,即無法調用(不是人用眼睛看不到那個代碼,除非用某種加密或者混淆方法,造成現實上的困難,但這不是封裝)。
要了解封裝,離不開“私有化”,就是將類或者函數中的某些屬性限制在某個區域之內,外部無法調用。
Python 中私有化的方法也比較簡單,就是在準備私有化的屬性(包括方法、數據)名字前面加雙下劃線。例如:
#!/usr/bin/env Python # coding=utf-8 __metaclass__ = type class ProtectMe: def __init__(self): self.me = "qiwsir" self.__name = "kivi" def __python(self): print "I love Python." def code(self): print "Which language do you like?" self.__python() if __name__ == "__main__": p = ProtectMe() print p.me print p.__name
運行一下,看看效果:
$ python 21102.py qiwsir Traceback (most recent call last): File "21102.py", line 21, in <module> print p.__name AttributeError: 'ProtectMe' object has no attribute '__name'
查看報錯信息,告訴我們沒有__name 那個屬性。果然隱藏了,在類的外面無法調用。再試試那個函數,可否?
if __name__ == "__main__": p = ProtectMe() p.code() p.__python()
修改這部分即可。其中 p.code() 的意圖是要打印出兩句話:"Which language do you like?"和"I love Python.",code() 方法和__python() 方法在同一個類中,可以調用之。後面的那個 p.__Python() 試圖調用那個私有方法。看看效果:
$ python 21102.py Which language do you like? I love Python. Traceback (most recent call last): File "21102.py", line 23, in <module> p.__python() AttributeError: 'ProtectMe' object has no attribute '__python'
如願以償。該調用的調用了,該隱藏的隱藏了。
用上面的方法,的確做到了封裝。但是,我如果要調用那些私有屬性,怎麼辦?
可以使用 property 函數。
#!/usr/bin/env Python # coding=utf-8 __metaclass__ = type class ProtectMe: def __init__(self): self.me = "qiwsir" self.__name = "kivi" @property def name(self): return self.__name if __name__ == "__main__": p = ProtectMe() print p.name
運行結果:
$ python 21102.py kivi
從上面可以看出,用了 @property 之後,在調用那個方法的時候,用的是 p.name 的形式,就好像在調用一個屬性一樣,跟前面 p.me 的格式相同。