從封裝自己的意思去理解,封裝就好像是拿來一個麻袋,把小貓,小狗,小王八,還有egon一塊兒裝進麻袋,而後把麻袋封上口子。但其實這種理解至關片面編程
你錢包的有多少錢(數據的封裝)socket
你的性取向(數據的封裝)編程語言
你撒尿的具體功能是怎麼實現的(方法的封裝)函數
封裝數據的主要緣由是:保護隱私(做爲男人的你,臉上就寫着:我喜歡男人,你懼怕麼?)測試
封裝方法的主要緣由是:隔離複雜度(快門就是傻瓜相機爲傻瓜們提供的方法,該方法將內部複雜的照相功能都隱藏起來了,好比你沒必要知道你本身的尿是怎麼流出來的,你直接掏出本身的接口就能用尿這個功能)spa
提示:在編程語言裏,對外提供的接口(接口可理解爲了一個入口),就是函數,稱爲接口函數,這與接口的概念還不同,接口表明一組接口函數的集合體。code
封裝其實分爲兩個層面,但不管哪一種層面的封裝,都要對外界提供好訪問你內部隱藏內容的接口(接口能夠理解爲入口,有了這個入口,使用者無需且不可以直接訪問到內部隱藏的細節,只能走接口,而且咱們能夠在接口的實現上附加更多的處理邏輯,從而嚴格控制使用者的訪問)對象
第一個層面的封裝(什麼都不用作):建立類和對象會分別建立兩者的名稱空間,咱們只能用類名.或者obj.的方式去訪問裏面的名字,這自己就是一種封裝繼承
注意:對於這一層面的封裝(隱藏),類名.和實例名.就是訪問隱藏屬性的接口
第二個層面的封裝:類中把某些屬性和方法隱藏起來(或者說定義成私有的),只在類的內部使用、外部沒法訪問,或者留下少許接口(函數)供外部訪問。
在python中用雙下劃線的方式實現隱藏屬性(設置成私有的)
類中全部雙下劃線開頭的名稱如__x都會自動變造成:_類名__x的形式:
class A: __N = 0 # 類的數據屬性就應該是共享的,可是語法上是能夠把類的數據屬性設置成私有的如__N,會變形爲_A__N def __init__(self): self.__X = 10 # 變形爲self._A__X def __foo(self): # 變形爲_A__foo print('from A') def bar(self): self.__foo() # 只有在類內部才能夠經過__foo的形式訪問到.
這種自動變形的特色:
類中定義的__x只能在內部使用,如self.__x,引用的就是變形的結果。
這種變形其實正是針對內部的變形,在外部是沒法經過__x這個名字訪問到的。
在子類定義的__x不會覆蓋在父類定義的__x,由於子類中變造成了:_子類名__x,而父類中變造成了:_父類名__x,即雙下滑線開頭的屬性在繼承給子類時,子類是沒法覆蓋的。
注意:對於這一層面的封裝(隱藏),咱們須要在類中定義一個函數(接口函數)在它內部訪問被隱藏的屬性,而後外部就可使用了
這種變形須要注意的問題是:
# 對象測試 a = A() print(a._A__N)
0
# 對象測試 print(a._A__X)
10
# 類測試 print(A._A__N)
0
# 類測試 try: print(A._A__X) # 對象私有的屬性 except Exception as e: print(e)
type object 'A' has no attribute '_A__X'
a = A() print(a.__dict__)
{'_A__X': 10}
a.__Y = 1
print(a.__dict__)
{'_A__X': 10, '__Y': 1}
# 正常狀況 class A: def fa(self): print('from A') def test(self): self.fa() class B(A): def fa(self): print('from B') b = B() b.test()
from B
# 把fa定義成私有的,即__fa class A: def __fa(self): # 在定義時就變形爲_A__fa print('from A') def test(self): self.__fa() # 只會與本身所在的類爲準,即調用_A__fa class B(A): def __fa(self): print('from B') b = B() b.test()
from A
python並不會真的阻止你訪問私有的屬性,模塊也遵循這種約定,若是模塊中的變量名_private_module以單下劃線開頭,那麼from module import *時不能被導入該變量,可是你from module import _private_module依然是能夠導入該變量的
其實不少時候你去調用一個模塊的功能時會遇到單下劃線開頭的(socket._socket,sys._home,sys._clear_type_cache),這些都是私有的,原則上是供內部調用的,做爲外部的你,獨斷獨行也是能夠用的,只不過顯得稍微傻逼一點點
python要想與其餘編程語言同樣,嚴格控制屬性的訪問權限,只能藉助內置方法如__getattr__,詳見面向對象高級部分。
多態是在定義角度
多態性是在調用角度(使用角度)
class A: def fa(self): print('from A') def test(self): self.fa() class B(A): def fa(self): print('from B') b = B() b.test()
from B
class A: def __fa(self): print('from A') def test(self): self.__fa() class B(A): def __fa(self): print('from B') b = B() b.test()
from A
注:__名字,這種語法只在定義的時候纔有變形的效果,若是類或對象已經產生了,就不會有變形的效果了。