封裝很容易理解,就是把一個東西包起來。那麼什麼都能包起來嗎,我還能打開它嗎?今天我們就一起來聊一聊。
1、爲什麼要封裝
相信每個人都不希望別人的手機連上自己的音響吧,我想聽這個歌,你非要給我放那個,我又那你沒辦法。
例如:
class Dog():
name = '哈士奇'
def speak(lala):
print(f'我是{lala.name}')
dog = Dog()
dog.name = '德牧'
dog.speak()
dog.name = '二哈'
dog.speak()
我是德牧
我是二哈
這個代碼中,我的狗的名字可以被別人隨便改,這我當然不希望發生。
其實是有辦法的,那就是封裝。
2、怎麼封裝?
我要封裝,就是希望別人找不到我的類中的屬性,那我把這個屬性隱藏起來就好了。
2.1 雙下劃線開頭
這裏可以使用雙下劃線開頭的命名來隱藏屬性,我們來看一下:
class Dog():
__name = '哈士奇'
def speak(lala):
print(f'我是{lala.__name}')
dog = Dog()
dog.__name
AttributeError Traceback (most recent call last)
in ()
6 # dog.__name = ‘德牧’
7 # dog.speak()
----> 8 dog.__name
AttributeError: ‘Dog’ object has no attribute ‘__name’
加了兩個下劃線,它就找不到這個屬性了。
事實上,是只有在類的內部,才能訪問或者修改這個屬性。
class Dog():
__name = '哈士奇'
def speak(lala):
print(f'我是{lala.__name}')
dog = Dog()
dog.__name = '德牧'
dog.speak()
結果:
我是哈士奇
也就是說,這樣的話,如果我們想要訪問或者是修改這個屬性,需要在類的內部自己定義一個方法,來進行訪問和修改。關於這個我們後面再說。
- 事情的真相:
這個其實並不是真的隱藏起來了,它只是給這個屬性自動的改了個名字,讓你找不到它了。改名字的規則是這樣的:__屬性名
–>_類名__屬性名
,我們可以嘗試一下,還是剛纔那個程序:
class Dog():
__name = '哈士奇'
def speak(lala):
print(f'我是{lala.__name}')
dog = Dog()
print(dog._Dog__name)
dog._Dog__name = '德牧'
dog.speak()
結果:
哈士奇
我是德牧
所以說,我們隱藏不是我們的目的,我們的目的就是給這個私有屬性做一個標誌,告訴別人不要更改它,所以我們通常使用下一種方式。
2.2 單下劃線開頭
一般,以單下劃線開頭的屬性都是私有屬性,這樣做的好處:
- 方便書寫
- 提醒別人這是私有屬性
- 在外部可以訪問和修改
3、封裝的好處
- 封裝是面向對象的三大特性之一
- 標誌了私有屬性
- 在類的內部定義了setter()和getter()方法,確保了數據安全,同時增加了數據驗證。
- 增加了讀改數據的複雜程度,同時確保了安全
4、完整的封裝實例
class Dog():
def __init__(self,name,age):
self._name = name
if age>0:
self._age = age
else:
flag = input(f'您要輸入的年齡是不是{-age}歲,y/n')
if flag == 'y':
self._age = -age
else:
print('您輸入的年齡不合法')
def speak(lala):
print(f'我是{lala._name},我{lala._age}歲了')
def set_age(self,age):
self.age = age
dog = Dog('二哈',-12)
dog.speak()
您要輸入的年齡是不是12歲,y/n
y
我是二哈,我12歲了