一、什么是封装
什么是封装,就是将复杂的丑陋的,隐私的细节隐藏到内部,对外提供简单的使用接口,对外隐藏内部实现细节,并提供访问的接口
二、为什么需要封装
两个目的:1.为了保证关键数据的安全性
2.对外部隐藏实现细节,隔离复杂度
三、什么时候应该封装
当有一些数据不希望外接可以直接修改时或是有一些函数不希望给外界使用时。
四、如何使用封装
封装函数的基本使用方法
1 class Person: 2 def __init__(self,id_number,name,age): 3 self.__id_numder = id_number 4 self.name = name 5 self.age = age 6 7 def show_id(self): 8 print(self.__id_numder) 9 10 p = Person('111','jerry',20)11 12 p.__id_numder = '222'13 print(p.__id_numder)14 15 p.show_id()
1 class PC: 2 def __init__(self,name,kind,price): 3 self.name = name 4 self.kind = kind 5 self.price = price 6 7 def open(self): 8 print('接通电源') 9 print('读取BIOS')10 self.__check_hardware()11 print('主引导记录')12 self.__record()13 print('硬盘启动')14 self.__read_disk()15 print('进入操作系统')16 17 def __check_hardware(self):18 print('硬件自检1...')19 print('硬件自检2...')20 print('硬件自检3...')21 print('硬件自检4...')22 23 def __record(self):24 print('主引导记录的结构')25 print('分区表')26 27 def __read_disk(self):28 print('情况A:卷引导记录')29 print('情况B:扩展分区和逻辑分区')30 print('情况C:启动管理器')31 32 pc1 = PC('玩家国度','台式',20000)33 34 pc1.open()
被封装的内容的特点:
1.外界不能直接访问
2.内部依然可以使用
在我们学习了封装后就可以控制属性的权限
在python只要两种权限:
1.公开的,默认就是公开的
2.私有的,只能由当前类自己使用的
五、在外界访问私有的内容
属性虽然封装了,但是还是需要使用的,在外界如何访问?答案是通过定义类完成对私有属性的修改和访问。
对外部隐藏内部的实现细节,并提供访问的接口
好处:
1.提高安全性
2.隔离复杂度
语法:将要封装的属性或方法名称前加上上下划线
访问被隐藏的属性:
提供用于访问和修改的方法
使用propert装饰器可以将一个方法伪装成普通属性,保证属性之间调用方法一致
封装的实现原理,替换变量名称
例如:这是一个下载器类,需要提供一个缓存大小这样的属性,缓存大小不能超过内存限制
1 class Download: 2 def __init__(self,name,url,buffer_size): 3 self.name = name 4 self.url = url 5 self.__buffer_size = buffer_size 6 7 def start_download(self): 8 if self.__buffer_size <= 1024*1024: 9 print('正在下载%s,缓存大小为%sb'%(self.name,self.__buffer_size))10 else:11 print('缓存过大')12 13 def set_buffer_size(self,new_size):14 #在方法中添加额外逻辑15 if not type(new_size) == int:16 print('求求你输个数字好不好...')17 else:18 self.__buffer_size = new_size19 20 def get_buffer_size(self):21 print(self.__buffer_size)22 23 d1 = Download('小猪佩奇','www.pig.com',2048*1024)24 25 d1.start_download()26 #通过函数修改内部封装的属性27 d1.set_buffer_size(1024*1024)28 d1.start_download()29 #通过函数访问内部封装的属性30 d1.get_buffer_size()
六、property装饰器
通过方法来修改或访问属性,本身没什么问题,但是这给对象的使用者带来了麻烦
使用必须知道哪些是普通属性,哪些是私有属性,需要使用不同的方式来调用他们
property装饰就是为了使得调用方式一致
三个相关的装饰器:
1.@property 该装饰器在获取属性的方法上
2.@key.setter 该装饰器用在修改属性方法上
3.@ket.deleter 该装饰器用在删除属性的方法上
注意:key是被property装饰的方法的名称,也就是属性的名称
内部会创建一个对象,变量名就是函数名称
所以在使用setter和deleter时,必须保证使用对象的名称取调用方法
所以是 key.setter
1 class Salary: 2 def __init__(self,name,salary): 3 self.__name = name 4 self.__salary = salary 5 6 @property 7 def salary(self): 8 return self.__salary 9 10 @salary.setter11 def salary(self,new_salary):12 if new_salary >= 10000:13 self.__salary = new_salary14 else:15 print('你看不起谁呢?')16 17 @salary.deleter18 def salary(self):19 del self.__salary20 21 p = Salary('jason','50000')22 23 p.salary = 5024 print(p.salary)25 26 del p.salary27 print(p.salary)
七、计算属性
计算属性指的是:属性的值,不能直接获得,必须通过计算才能获取
例题:一个正方形有两个属性:边长、面积。面积等于边长的平方,请计算正方形的面积
1 class Square: 2 def __init__(self,width): 3 self.width = width 4 5 @property 6 def area(self): 7 return self.width*self.width 8 9 s = Square(10)10 11 print(s.area)
八、接口的使用
接口是一组功能的集合,但是接口中仅包含功能的名字,不包含具体的是实现代码
接口是本质是一套协议标注,遵循这个标准的对象就能被调用
接口的目的就是为了提高扩展性:就例如电脑提前制定一套USB接口协议,只要你遵循该协议,你的设备就可以被电脑使用,不需要关心到底是鼠标还是键盘。
1 class USB: 2 def open(self): 3 pass 4 5 def close(self): 6 pass 7 8 def read(self): 9 pass10 11 def write(self):12 pass13 14 class Mouse(USB):15 def open(self):16 print('鼠标建立连接')17 18 def close(self):19 print('鼠标关闭连接')20 21 def read(self):22 print('鼠标正在获取光标位置')23 24 def write(self):25 print('鼠标不支持写入')26 27 class KeyBoard(USB):28 def open(self):29 print('键盘建立连接')30 31 def close(self):32 print('键盘关闭连接')33 34 def read(self):35 print('键盘正在获取按键字符')36 37 def write(self):38 print('键盘获取灯光信息')39 40 def pc(usb_device):41 usb_device.open()42 usb_device.read()43 usb_device.write()44 usb_device.close()45 46 m = Mouse()47 k = KeyBoard()48 pc(m)49 pc(k)
在上述案例中,PC的代码一旦完成后,后期无论什么样的设备只要遵循了USB接口协议,都能够被电脑所调用,接口主要是方便了对象的使用者,降低使用者的学习难度,只要学习一套使用的方法,就可以以不变应万变
九、abc模块
1 import abc 2 class AClass(metaclass=abc.ABCMeta): 3 4 @abc.abstractmethod 5 def run(self): 6 pass 7 8 class B(AClass): 9 def run(self):10 print('run')11 12 b = B()
接口是一套协议规范,明确子类们应该具备哪些功能,抽象类是用于强制要求子类必须按照协议中的规定来实现,然而,python不推崇限制你的语法,我们可以设计成鸭子类型,既然多个不同类对象具备相同的属性。对于使用者而言,就可以以不变应万变,轻松的使用各种对象。