1. 程式人生 > >python面向對象(二)之封裝

python面向對象(二)之封裝

面向 ret 引用 obj cap lock 推薦 簡單 rom

封裝定義:

   在程序設計中,封裝(Encapsulation)是對具體對象的一種抽象,即將某些部分隱藏起來,在程序外部看不到,其含義是其他程序無法調用。

  即“封裝”就是將抽象得到的數據和行為(或功能)相結合,形成一個有機的整體(即類);封裝的目的是增強安全性和簡化編程,使用者不必了解具體的實現細節,而只是要通過外部接口,一特定的訪問權限來使用類的成員。這就用到私有化,前面簡單的講了下,下面回具體將。

封裝的原因:

  封裝數據的主要原因是:保護隱私(把不想別人知道的東西封裝起來)

  封裝方法的主要原因是:隔離復雜度(比如:電視機,我們看見的就是一個黑匣子,其實裏面有很多電器元件,對於用戶來說,我們不需要清楚裏面都有些元件,電視機把那些電器元件封裝在黑匣子裏,提供給用戶的只是幾個按鈕接口,用戶只需要知道通過按鈕就能對電視機的操作就行,而且也避免了用戶對其無意識的破環)。

封裝的封裝層次

    封裝分為兩個層面,但無論哪種層面的封裝,都要對外界提供好訪問你內部隱藏內容的接口(接口可以理解為入口,有了這個入口,使用者無需且不能夠直接訪問到內部隱藏的細節,只能走接口,並且我們可以在接口的實現上附加更多的處理邏輯,從而嚴格控制使用者的訪問)。

  • 第一個層面的封裝(什麽都不用做):創建類和對象會分別創建二者的名稱空間,我們只能用類名.或者obj.的方式訪問裏面的名字,這本身就是一種封裝。對於這一層面的封裝(隱藏),類名.和實例名.就是訪問隱藏屬性的接口。

  • 第二個層面的封裝:類中把某些屬性和方法隱藏起來(或者說定義成私有的),只在類的內部使用、外部無法訪問,或者留下少量接口(函數)供外部訪問。

這個層面的封裝就用到了私有化。在python中沒有像java中的關鍵子去控制訪問權限而用的是下劃線來控制。

python用加雙下劃線前綴表示私有。其中所有雙下劃線開頭的名稱如_ _ x都會自動變形成:**類名 _x**的形式,根據這個就可以直接調用私用屬性和方法,不過不建議那樣做。一般使用自己編寫的get,set方法去訪問或這用property進行訪問和設置。在後面的裝飾器會講。

class A:
    __N=0 #類的數據屬性就應該是共享的,但是語法上是可以把類的數據屬性設置成私有的如__N,會變形為_A__N
    def __init__(self):
        self
.__X=10 #變形為self._A__X def getX(self): #起名字時一般是屬性首字母大寫再在前面加get或者set return self.__X def setX(self,x): self.__X=x def __foo(self): #變形為_A__foo print('from A') def bar(self): self.__foo() #只有在類內部才可以通過__foo的形式訪問到. 

這種自動變形的特點:

    1、類中定義的__x只能在內部使用,如self.__x,引用的就是變形的結果。

    2、這種變形其實正是針對外部的變形,在外部是無法通過__x這個名字訪問到的。

    3、在子類定義的_ _ x不會覆蓋在父類定義的_ _ x,因為子類中變形成了:_ 子類名 _ _ x,而父類中變形成了:父類名 _ _ x,即雙下滑線開頭的屬性在繼承給子類時,子類是無法覆蓋的。

封裝的優點:

  • 通過隱藏對象的屬性來保護對象內部的狀態,安全性提高。
  • 提高了代碼的可用性和可維護性,因為對象的行為可以被單獨的改變或者是擴展。
  • 禁止對象之間的不良交互提高模塊化,各取所需,利於分工。

補充知識:

  上面講了雙下劃線,下來講下但下劃線和前後都有下劃線的情況

單下劃線開頭(_)

   在一個模塊中以單下劃線開頭的變量和函數被默認當作內部函數,如果使用from a_module import * 導入時,這部分變量和函數不會被導入。不過值得註意的是,如果使用 import a_module 這樣導入模塊,仍然可以用a_module._some_var 這樣的形式訪問到這樣的對象。

雙下劃開頭結尾

  雙下劃線開頭雙下劃線結尾的是一些 Python 的特殊對象,如類成員的 _ _ init_ _ ,_ _ del _ , _ new _ _ , _ str _等。** Python 官方推薦永遠不要將這樣的命名方式應用於自己的變量或函數,**而是按照文檔說明來使用。

python面向對象(二)之封裝