python之面向物件編制之封裝
1.什麼是封裝
封:屬性對外是隱藏的,單對內是開放的
裝:申請一個名稱空間,往裡裝入一系列名字/屬性
2.為什麼要封裝
封裝資料屬性的目的
首先定義屬性的目的就是為了給類外部的使用而使用
隱藏之後是為了不讓外部直接使用,需要內部開闢一個介面
然後讓類外部的使用通過介面間接的操作隱藏的屬性
精髓在於:我們可以在介面之上附加任意邏輯,從而嚴格控制使用者對屬性操作
封裝函式屬性
首先定義屬性的目的就是為了給類外部的使用而使用的
隱藏函式屬性是為了不讓外部直接使用,需要類的內部開闢一個介面
然後在介面內去呼叫隱藏的功能
精髓在於:隔離了複雜度
3.如何封裝
如何隱藏:在屬性前面加上__開頭
1.這種隱藏僅僅只是之中語法上的變形操作
2.這種語法上的變形只在類定義階段發生一次,因為類體程式碼僅僅只在類定義階段檢測一次
3.這種隱藏是對外不對內的,即在類的內部可以直接訪問,而在類的外側無法直接訪問
原因是:
在類定義階段,類的體內程式碼統一發生一次變形
4.如果不想讓子類的方法覆蓋父類,可以將該方法前加一個__開頭
一.資料屬性發封裝
例: # class People: #隱藏僅僅只是一種語法上的變形操作 # __country='China' #_People__country='China' # __n=100 #_People__n=100 # def __init__(self,name,age,sex): # self.__name=name #self._People__name=name # self.age=age # self.sex=sex # # def eat(self): # print('eat.....') # print(People.__country) #People._People__country # print(self.__name) #self._People__name # People.eat(123) # print(People.__country) # peo1=People('egon',18,'male') # peo1.eat() # print(peo1.__name) #外面不能呼叫,屬性的名字已經發生改變了 # print(People.__dict__) # print(People.__country) # print(People._People__country) # People.__x=11 # print(People.__dict__)
例2:內部屬性全部隱藏,設定可以介面查詢,和修改的介面,設定操作許可權
class People: def __init__(self,name,age): self.__name=name self.__age=age def tell_info(self): print('%s:%s' %(self.__name,self.__age)) def set_info(self,name,age): if type(name) is not str: # print('使用者名稱必須為str型別') # return raise TypeError('使用者名稱必須為str型別') if type(age) is not int: # print('年齡必須為int型別') # return raise TypeError('年齡必須為int型別') self.__name=name self.__age=age peo1=People('egon',18) # peo1.name=123 #外部不能直接修改。直接報錯 # peo1.age # peo1.tell_info() peo1.set_info('egon',19) #設定一個開放介面, # peo1.tell_info()
例2.封裝加繼承屬性的查詢
# class Foo:
# def __f1(self): #_Foo__f1
# print('Foo.f1')
#
# def f2(self):
# print('Foo.f2')
# self.__f1() #self._Foo__f1
#
# class Bar(Foo):
# def __f1(self): #_Bar__f1
# print('Bar.f1')
#
# obj=Bar()
# obj.f2()
二.函式屬性的封裝
property裝飾器用於將被裝飾的方法偽裝成一個數據屬性,在使用時可以不加括號而直接引用
class People:
def __init__(self,name,weight,height):
self.name=name
self.weight=weight
self.height=height
@property
def bmi(self):
return self.weight / (self.height**2)
peol=People('egon',75,1.8)
print(peol.bmi)
class People:
def __init__(self, name, weight, height):
self.__name = name #資料熟悉隱藏+函式屬性隱藏
self.__weight = weight
self.__height = height
@property
def bmi(self):
return self.__weight / (self.__height ** 2)
peol=People('egon',75,1.8)
print(peol.__dict__)
print(peol.bmi)
例,函式封裝之 檢視、修改、刪除,用法:
class People:
def __init__(self,name):
self.__name=name
@property # 檢視obj.name
def name(self):
return '<名字是:%s>' %self.__name
@name.setter #修改obj.name=值
def name(self,name):
if type(name) is not str:
raise TypeError('名字必須是str型別傻叉')
self.__name=name
@name.deleter #刪除del obj.name
def name(self):
# raise PermissionError('不讓刪') #raise是個異常報錯提示命令
print('不讓刪除傻叉')
# del self.__name
peo1=People('egon')
# print(peo1.name)
# print(peo1.name) #檢視
# peo1.name='EGON' #修改
# print(peo1.name)
del peo1.name #刪除
2.函式封裝:簡潔使用方法
class People:
def __init__(self,name):
self.__name=name
def tell_name(self):
return '<名字是:%s>' %self.__name
def set_name(self,name):
if type(name) is not str:
raise TypeError('名字必須是str型別傻叉')
self.__name=name
def del_name(self):
print('不讓刪除傻叉')
name=property(tell_name,set_name,del_name) #python中簡潔使用方法
peo1=People('egon')
print(peo1.name)
peo1.name='EGON'
print(peo1.name)
del peo1.name