python 3 封裝
從封裝本身的意思去理解,封裝就好像是拿來乙個麻袋,把小魚,小蝦,小王八,一起裝進麻袋,然後把麻袋封上口子。照這種邏輯看,封裝=『隱藏』,這種理解是相當片面的。
先看如何隱藏
在python中用雙下劃線開頭的方式將屬性隱藏起來(設定成私有的)
其實這僅僅這是一種變形操作
類中所有雙下劃線開頭的名稱如__x都會自動變形成:_類名__x的形式:
classa:__n=0 #類的資料屬性就應該是共享的,但是語法上是可以把類的資料屬性設定成私有的如__n,會變形為_a__n
def __init__(self):
self.__x=10 #變形為self._a__x
def __foo(self): #變形為_a__foo
print('from a')defbar(self):
self.__foo() #只有在類內部才可以通過__foo的形式訪問到.
a._a__n是可以訪問到的,即這種操作並不是嚴格意義上的限制外部訪問,僅僅只是一種語法意義上的變形。
view code
這種自動變形的特點:
類種定義的__x只能在內部使用,如self.__x,引用的就是變形的結果。
這種變形其實正是針對外部的變形,在外部是無法通過__x這個名字訪問到的。
在子類定義的__x不會覆蓋在父類定義的__x,因為子類中變形成了:_子類名__x,而父類中變形成了:_父類名__x,即雙下劃線開頭的屬性在繼承給子類時,子類是無法覆蓋的。
對於這一層面的封裝(隱藏),我們需要在類中定義乙個函式(介面函式)在它內部訪問被隱藏的屬性,然後外部就可以使用了
這種變形需要注意的問題是:
1.這種機制也沒有真正意義上限制我們從外部直接訪問屬性,知道了雷鳴和屬性名就可以拼出名字:_類名__屬性,然後皆可以訪問了,如a._a__n
2.變形的過程只在類的定義時放生一次,在定義後的賦值操作,不會變形
3.在繼承中,父類如果不想讓子類渡改自己的方法,可以將方法定義為私有的
python並不會真的阻止你訪問私有的屬性,模組也遵循這種約定,如果模組名以單下劃線開頭,那麼from module import *時不能被匯入,但是你from module import _private_module依然是可以匯入的其實很多時候你去呼叫乙個模組的功能時會遇到單下劃線開頭的(socket._socket,sys._home,sys._clear_type_cache),這些都是私有的,原則上是供內部呼叫的。作為外部也可以用,只過寫出**比較傻了,python要想與其他程式語言一樣,嚴格控制屬性的訪問許可權,只能借助內建方法如__getattr__
#先看如何隱藏
classfoo:__n=111111 #_foo__n
def __init__(self,name):
self.__name=name #self._foo__name=name
def __f1(self): #_foo__f1
print('f1')deff2(self):
self.__f1() #self._foo__f1()
f=foo('egon')#print(f.__n)
#f.__f1()
#f.__name
f.f2()#通f
#這種隱藏需要注意的問題:
#1:這種隱藏只是一種語法上變形操作,並不會將屬性真正隱藏起來
print(foo.__dict__)print(f.__dict__)print(f._foo__name)print(f._foo__n)#2:這種語法級別的變形,是在類定義階段發生的,並且只在類定義階段發生
foo.__x=123123123123123123123123123123123123123123
print(foo.__dict__)print(foo.__x)
f.__x=123123123
print(f.__dict__)print(f.__x)#3:在子類定義的__x不會覆蓋在父類定義的__x,因為子類中變形成了:_子類名__x,而父類中變形成了:_父類名__x,即雙下滑線開頭的屬性在繼承給子類時,子類是無法覆蓋的。
classfoo:def __f1(self): #_foo__f1
print('foo.f1')deff2(self):
self.__f1() #self._foo_f1
classbar(foo):def __f1(self): #_bar__f1
print('bar.f1')
b=bar()
b.f2()#封裝不是單純意義的隱藏
#1:封裝資料屬性:將屬性隱藏起來,然後對外提供訪問屬性的介面,關鍵是我們在介面內定製一些控制邏輯從而嚴格控制使用對資料屬性的使用
classpeople:def __init__(self,name,age):if notisinstance(name,str):raise typeerror('%s must be str' %name)if notisinstance(age,int):raise typeerror('%s must be int' %age)
self.__name=name
self.__age=agedeftell_info(self):print('' %(self.__name,self.__age))defset_info(self,x,y):if notisinstance(x,str):raise typeerror('%s must be str' %x)if notisinstance(y,int):raise typeerror('%s must be int' %y)
self.__name=x
self.__age=y
p=people('egon',18)
p.tell_info()#p.set_info('egon','19')
p.set_info('egon',19)
p.tell_info()#2:封裝函式屬性:為了隔離複雜度
#取款是功能,而這個功能有很多功能組成:插卡、密碼認證、輸入金額、列印賬單、取錢
#對使用者來說,只需要知道取款這個功能即可,其餘功能我們都可以隱藏起來,很明顯這麼做
#隔離了複雜度,同時也提公升了安全性
classatm:def __card(self):print('插卡')def __auth(self):print('使用者認證')def __input(self):print('輸入取款金額')def __print_bill(self):print('列印賬單')def __take_money(self):print('取款')defwithdraw(self):
self.__card()
self.__auth()
self.__input()
self.__print_bill()
self.__take_money()
a=atm()
a.withdraw()#_x=123
示例**
python第三次作業
問題1 小學生算術能力測試系統 設計乙個程式,用來實現幫助小學生進行百以內的算術練習,它具有以下功能 提供10道加 減 乘或除四種基本算術運算的題目 練習者根據顯示的題目輸入自己的答案,程式自動判斷輸入的答案是否 正確並顯示出相應的資訊 import random count 0 right 0 w...
python學習第三次
如果說年利率是6.7 本利是每年翻滾,則多少年後本錢會翻倍 in 1 benqian 100000 year 0 存錢需要翻本的年數 while benqian 200000 benqian benqian 1 0.067 year 1 year year 1 print year out 1 11...
python第三次學習
1的學習 這一課時主要講了python的特點 簡史 應用領域以及環境等,還講了python語言的規範性 2 2的學習 變數定義 注釋寫法 行注釋 開頭,單獨成行或者在 的後面 塊注釋 好幾行的 或內容,以三個連續的單引號開頭和結束 原則 恰當 易懂 不是越多越好 對不容易懂的 新增注釋 變數概念 變...