封装:是将复杂的丑陋的,隐私的细节隐藏到内部,对外提供简单的使用接口, 对外隐藏内部实现细节,并提供访问的接口;
为什么需要封装
两个目的:
1.为了保证 关键数据的安全性;2.对外部隐藏实现细节,隔离复杂度
什么时候应该封装?
当有一些数据不希望外界可以直接修改时;当有一些函数不希望给外界使用时;
被封装的内容的特点:
1.外界不能直接访问 2.内部依然可以使用
权限
学习了封装后就可以控制属性的权限
在python只要两种权限: 1.公开的.默认就是公开的; 2.私有的,只能由当前类自己使用
在外界访问私有的内容:
属性虽然被封装了,但是还是需要使用的,在外界如何访问
通过定义方法类完成对私有属性的修改和访问
封装案例1:
#222 我们通过对__id_number进行修改,来对比外部是否能对__开头的属性进行修改.
# p.show_id() #12312 内部值并没有发生变化,所以通过__开头进行封装,外部通过普通方法并不能对内部的值进行修改.
案例二:
1 class PC: 2 def __init__(self,price,color,kind): 3 self.color=color 4 self.price=price 5 self.kind=kind 6 def open(self): 7 print('接通电源') 8 self.__check_device() 9 print('载入内核') 10 print('初始化内核') 11 self.__start_service() 12 print('启动GUI') 13 self.__login() 14 15 def __check_device(self): 16 print('检测硬件1') 17 print('检测硬件2') 18 print('检测硬件3') 19 print('检测硬件4') 20 def __start_service(self): 21 print('启动服务1') 22 print('启动服务2') 23 print('启动服务3') 24 def __login(self): 25 print('login..') 26 27 28 pc=PC(6000,'white','lenvo') 29 pc.open() 30 31 打印结果 32 33 ''' 34 接通电源 35 检测硬件1 36 检测硬件2 37 检测硬件3 38 检测硬件4 39 载入内核 40 初始化内核 41 启动服务1 42 启动服务2 43 启动服务3 44 启动GUI 45 login.. 46 47 '''
案例三:
class Downloader: def __init__(self,filename,url,buffer_size): self.filename=filename self.url=url self.__buffer_size=buffer_size def start_download(self): if self.__buffer_size<=1024*1024: print('开始下载...') else: print('内存不足..') d=Downloader('葫芦娃','http://www.baidu.com',1024*1024) d.buffer_size=1024*1024*10 #类中__开头的属性无法直接访问,其属性对赢得值也无法修改. d.start_download() ##开始下载... class Downloader: def __init__(self,filename,url,buffer_size): self.filename=filename self.url=url self.__buffer_size=buffer_size def start_download(self): if self.__buffer_size<=1024*1024: print('开始下载...') print('当前缓冲区大小为%s'%self.__buffer_size) else: print('内存不足..') def set_buffer_size(self,size): self.__buffer_size=size def get_buffer_size(self): return self.__buffer_size d=Downloader('葫芦娃','http://www.baidu.com',1024*1024) #通过函数去修改内部封装的属性 d.set_buffer_size(1024*1024/2) #通过函数访问内部封装的属性 print(d.get_buffer_size()) d.start_download() ## 524288.0 开始下载... 当前缓冲区大小为524288.0
@property @key.setter @key.deleter
@property 装饰器(访问属性时,只需实例对象 点 函数名,切记函数名后不需加括号) @方法.setter(修改经property装饰的函数的内部属性) @方法.deleter
把原本私有的属性,伪装成普通的属性,对于使用者就没有区别了
案例一:
class A: def __init__(self,name,key): self.name=name self.__key=key def get_key(self): return self.__key def set_key(self,new_key): self.__key=new_key @property def key(self): return self.__key @key.setter def key(self,new_key): self.__key = new_key print('run...') print(self.__key) @key.deleter
def key(self):
print('不允许删除该属性') del self.__key a=A('zan',123) # print(a.name) # zan # print(a.get_key()) #通过调用函数访问__开头的属性 #32 # # print(a.key) #加了装饰器之后的访问属性方式 # 32 print(a.key) #打印的是@property里面的return self.__key 的值,有property装饰器,直接a.key这个函数 a.key=321 #要修改成的值 print(a.key) # 查看修改结果 ##### 123 run... 321 321
总结:
property装饰器
通过方法来修改或访问属性,本身没什么问题,但是这给对象的使用者带来了麻烦.
使用必须知道哪些是普通属性,哪些是私有属性,需要使用不同的方式来调用他们
property装饰就是为了使得调用方式一致
有三个相关的装饰器
```python
1.property 该装器用在获取属性的方法上
2.@key.setter 该装器用在修改属性的方法上
3.@key.deleter 该装器用在删除属性的方法上
注意:key是被property装饰的方法的名称 也就是属性的名称
内部会创建一个对象 变量名称就是函数名称
所以在使用setter和deleter时 必须保证使用对象的名称取调用方法
所以是 key.setter
```
封装的原理
就是在加载类的时候,把\_\_替换成了 \_类名\__
案例一:
案例二:
封装:
对外部隐藏内部的实现细节,并提供访问的接口
好处:
1.提高安全性
2.隔离复杂度
语法:将要封装的属性或方法名称前加上双下划线
访问被隐藏的属性:
提供用于访问和修改的方法
使用property装饰器可以将一个方法伪装成普通属性,保证属性之间调用方法一致
封装的实现原理 ,替换变量名称
封装的计算属性:(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) p1=People('egon',75,1.85) print(p1.bmi) #直接实例对象 点 方法名称就可以了