封装- --接口,抽象, 鸭子类型 #22
Posted 灵虚御风
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了封装- --接口,抽象, 鸭子类型 #22相关的知识,希望对你有一定的参考价值。
知识点
1.封装
1.封装.py
1 ‘‘‘‘‘‘ 2 """ 3 封装: 4 """ 5 6 """ 7 1.什么是封装? 8 就是将复杂的丑陋的,隐私的细节,隐藏到内部,对外提供简单的使用接口 9 10 即:对外隐藏内部实现细节,并提供访问接口 11 """ 12 """ 13 2.为什么需要封装? 14 两个目的: 15 1.为了保证 关键数据的安全性 16 2.对外部隐藏实现细节,隔离复杂度 17 """ 18 """ 19 3.什么时候应该封装? 20 当有一些数据不希望外界可以直接修改时 -- 安全性 21 ? 当有一些函数不希望给外界使用时, 22 -- 复杂度 23 """ 24 """ 25 4.被封装的内容的特点: 26 1.外界不能直接访问 27 2.内部依然可以使用 28 29 5.权限: 30 学习封装后可以控制属性的权限 31 在Python中只有两种权限, 32 1.公开的,默认就是公开的 33 2.私有的,只有内部(当前类自己)可以使用 34 """ 35 36 """ 37 如何使用? 38 语法: 39 """ 40 class Person: 41 def __init__(self,id_number,name,age): 42 self.__is_number = id_number 43 self.name = name 44 self.age = age 45 def show_id(self): 46 print(self.__is_number) 47 p = Person(‘2222222‘,‘llx‘,‘24‘) 48 p.__id_number = ‘1111‘ 49 print(p.__id_number) # 1111 50 # __id_number 被封装 51 p.show_id() # 2222222
2.封装方法.py
1 """""" 2 """正常方法""" 3 4 class PC: 5 def __init__(self,price,kind,color): 6 self.price = price 7 self.kind = kind 8 self.color = color 9 def open(self): 10 print(‘接通电源‘) 11 print(‘检测硬件1‘) 12 print(‘检测硬件2‘) 13 print(‘检测硬件3‘) 14 print(‘检测硬件4‘) 15 print(‘载入内核‘) 16 print(‘初始化内核‘) 17 print(‘启动GUI‘) 18 print("启动服务1") 19 print("启动服务2") 20 print("启动服务3") 21 print("启动服务4") 22 print("login....") 23 print("login....") 24 print("login....") 25 26 p = PC(20000,‘ovie‘,‘red‘) 27 print(p.__dict__) # {‘price‘: 20000, ‘kind‘: ‘ovie‘, ‘color‘: ‘red‘} 28 p.open() 29 """ 30 值: 31 接通电源 32 检测硬件1 33 检测硬件2 34 检测硬件3 35 检测硬件4 36 载入内核 37 初始化内核 38 启动GUI 39 启动服务1 40 启动服务2 41 启动服务3 42 启动服务4 43 login.... 44 login.... 45 login.... 46 """ 47 48 """封装方法""" 49 """ 语法 : __名称(双下划綫+类属性(初始化值)或方法(函数名))""" 50 class PC: 51 def __init__(self,price,kind,color): 52 self.price = price 53 self.kind = kind 54 self.color = color 55 56 def open(self): 57 print(‘接通电源‘) 58 # 封装检查硬件调用 59 self.__check() 60 print(‘载入内核‘) 61 print(‘初始化内核‘) 62 self.__run() 63 print(‘启动GUI‘) 64 self.__login() 65 def __run(self): 66 print("启动服务1") 67 print("启动服务2") 68 print("启动服务3") 69 print("启动服务4") 70 def __check(self): 71 print(‘检测硬件1‘) 72 print(‘检测硬件2‘) 73 print(‘检测硬件3‘) 74 print(‘检测硬件4‘) 75 def __login(self): 76 print("login....") 77 print("login....") 78 print("login....") 79 p = PC(40000,‘opp‘,‘蓝色‘) 80 p.open() 81 """ 82 接通电源 83 检测硬件1 84 检测硬件2 85 检测硬件3 86 检测硬件4 87 载入内核 88 初始化内核 89 启动服务1 90 启动服务2 91 启动服务3 92 启动服务4 93 启动GUI 94 login.... 95 login.... 96 login.... 97 """
3.如何访问被封装的属性.py
1 ‘‘‘‘‘‘ 2 ‘‘‘ 3 如何在外界通过方法来访问内部的被封装属性 4 ‘‘‘ 5 """ 6 案例: 7 这是一个下载器类, 8 需要提供一个缓存大小这样的属性 9 缓存大小不能超过内存限制 10 """ 11 # 定义一个下载器类 12 class Downloader: 13 # 属性 14 # filename 文件名 15 # url 域名 16 # buffer_size 缓存大小 17 def __init__(self,filename,url,buffer_size): 18 self.filename = filename 19 self.url = url 20 self.__buffer_size = buffer_size 21 # 缓存大小不能超过内存大小 22 def start_download(self): 23 # 内存大小:1024*1024 24 if self.__buffer_size <= 1024*1024: 25 print(‘开始下载....‘) 26 print(‘当前缓存器大小‘,self.__buffer_size) 27 else: 28 print(‘内存炸了‘) 29 # 设置(修改)缓存大小 30 # 一额外逻辑 31 def set_buffer_size(self,size): 32 # 缓存大小必须是整型 33 if type(size) == int: 34 print(‘缓存区大小修改成功‘) 35 self.__buffer_size = size 36 else: 37 print(‘大哥,缓存区大小必须是整型‘) 38 # 获取缓存区大小 39 def get_buffer_size(self): 40 return self.__buffer_size 41 p = Downloader(‘w3shool‘,‘http:\\www.w3school.atf‘,1024*1024) 42 #p.set_buffer_size(2048*2048) 43 44 # p.start_download() 45 46 # 访问方法 -- 原理:基于封装只有当前类可用 47 # 1.通过函数修改内部被封装的属性 48 p.set_buffer_size(2048*2048) 49 # 2.通过函数访问内部被封装的属性 50 # p.get_buffer_size() 51 print(p.get_buffer_size()) 52 53 p.start_download() 54 """ 55 缓存区大小修改成功 56 4194304 57 内存炸了 58 """
4.property装饰器.py
1 ‘‘‘‘‘‘ 2 """ 3 property装饰器 4 1.由来 5 基于下文访问被封装内容方法案例,在修改关键数据是应该再加些限制 6 7 当然通过这个方法访问这个类,本身没什么问题,但是这个对象的使用者带来了麻烦 8 9 在这种情况下,使用者,必须知道哪些是 普通属性, 哪些是私有属性,需要使用不同的方法来调用 他们. 10 11 property装饰就是为了使用调用方式一致 12 13 2.3种相关方法 -- 装饰器 14 1.@property 该装饰器用在获取属性的方法上 15 2.@key.setter 该装饰器用在修改属性方法上 16 3.@key.deleter 该装饰用在删除属性方法上 17 ps: 18 key 是被property装饰属性或方法的名称 19 也就是属性的名称 20 内部会创建一个对象 变量名称就是函数名称 21 所以在使用setter和deleter时 必须保证使用对象的名称取调用方法 22 所以是 key.setter 23 """ 24 # 案例 25 26 """ 27 案例: 28 这是一个下载器类, 29 需要提供一个缓存大小这样的属性 30 缓存大小不能超过内存限制 31 """ 32 # 定义一个下载器类 33 class Downloader: 34 # 属性 35 # filename 文件名 36 # url 域名 37 # buffer_size 缓存大小 38 def __init__(self,filename,url,buffer_size): 39 self.filename = filename 40 self.url = url 41 self.__buffer_size = buffer_size 42 43 # 获取缓存区大小 44 @property 45 def buffer_size(self): 46 return self.__buffer_size 47 # 缓存大小不能超过内存大小 48 49 @buffer_size.deleter 50 def buffer_size(self): 51 print("不允许删除该属性") 52 del self.__buffer_size 53 # 设置(修改)缓存大小 54 # 一额外逻辑 55 @buffer_size.setter 56 def buffer_size(self,size): 57 # 缓存大小必须是整型 58 if type(size) == int: 59 print(‘缓存区大小修改成功‘) 60 self.__buffer_size = size 61 else: 62 print(‘大哥,缓存区大小必须是整型‘) 63 p = Downloader(‘w3shool‘,‘http:\\www.w3school.atf‘,1024*1024) 64 #p.set_buffer_size(2048*2048) 65 66 # p.start_download() 67 68 # 访问方法 -- 原理:基于封装只有当前类可用 69 # 1.通过函数修改内部被封装的属性 70 #.buffer_size(2048*2048) 71 # 2.通过函数访问内部被封装的属性 72 # p.get_buffer_size() 73 74 75 p.start_download() 76 # 获取 77 #print(p.buffer_size) 78 # 修改 79 p.buffer_size = 1024*2096 80 # print(p.buffer_size) 81 # 删 82 del p.buffer_size 83 print(p.buffer_size)
5.封装的实现原理.py
1 ‘‘‘‘‘‘ 2 """ 3 1.Python实现封装的原理:替换变量名称 4 就是在加载类的时候,把__替换成__类名__ 5 Python一般不会要求程序必须怎么做怎么做 6 7 2.封装: 8 对外部隐藏内部的实现细节,并提供访问的接口 9 3.好处: 10 1.提高安全性, 11 2.隔绝复杂度 12 13 4.语法: 14 将要封装的属性或方法名称前加上双下划綫 15 16 5.访问被隐藏的属性: 17 提供用于访问和修改的方法 18 19 使用 property装饰器可以将一个方法伪装成普通属性,保持普通属性的属性的调用方法一致 20 """ 21 # 案例: 22 class A: 23 def __init__(self,key): 24 self.__key = key 25 26 # 获取方法 27 @property 28 def key(self): 29 return self.__key 30 # 修改方法 31 @key.setter 32 def key(self,re_key): 33 self.__key = re_key 34 return self.__key 35 # 删除方法 36 @key.deleter 37 def key(self): 38 del self.__key 39 p = A(‘assd‘) 40 # 获取方法 41 #print(p.key) # assd 42 # 修改方法 43 # p.key = ‘gfghfhjgg‘ 44 # print(p.key) # gfghfhjgg 45 # # 删除方法 46 # del p.key 47 print(p._A__key) # assd 48 49 p.__name = ‘jkhg‘ 50 print(p.__dict__) # {‘_A__key‘: ‘assd‘, ‘__name‘: ‘jkhg‘} 51 print("__key".replace("__","_A__")) # _A__key
6.作业,计算属性.py
1 """""" 2 """ 3 property 可以用来实现计算属性 4 5 计算属性指的是:属性的值, 6 不能直接获得,必须通过计算才能获取 7 8 """ 9 # 案例一 10 """正方形求面积""" 11 # 定义正方形 12 class Square: 13 # 定义正方形边 14 def __init__(self,width): 15 self.width = width 16 # 获取正方形的面积 17 @property 18 def area(self): 19 return self.width * self.width 20 @area.setter 21 def area(self,number): 22 self.width = number 23 return self.width 24 @area.deleter 25 def area(self): 26 del self.width 27 28 p = Square(5) 29 print(p.area) 30 p.width = 10 31 print(p.area) 32 # 案例二 33 # 练习: 定义一个类叫做person 34 # 包含三个属性 身高 体重 BMI 35 # BMI的值需要通过计算得来 公式 体重 / 身高的平方 36 class Person: 37 def __init__(self,high,weigh): 38 self.high = high 39 self.weigh = weigh 40 @property 41 def BMI(self): 42 return self.weigh / self.high / self.high 43 p = Person(180,87) 44 print(p.BMI)
2.接口和抽象类,鸭子类型
1.接口.py
1 ‘‘‘‘‘‘ 2 """ 3 接口: 4 是一组功能的集合,但是接口中仅包含功能的名字,不包含具体的实现代码 5 6 接口的本质: 7 是一套协议标准,遵循这个标准的对象就能被调用 8 9 接口的目的: 10 就是为了提高扩张性 11 12 接口:是一套协议内容,明确子类应该具备哪些功能 13 """ 14 """ 15 例如电脑提前指定制定一套USB接口协议,只要你遵循该协议,你的设备就可以被电脑使用,不需要关心到底是鼠标还是键盘 16 """ 17 # 案例 18 # usb接口 19 class USB: 20 def open(self): 21 pass 22 def close(self): 23 pass 24 def read(self): 25 pass 26 def write(self): 27 pass 28 # 鼠标 29 class Mouse(USB): 30 def open(self): 31 print("鼠标开机.....") 32 33 def close(self): 34 print("鼠标关机了...") 35 36 def read(self): 37 print("获取了光标位置....") 38 39 def write(self): 40 print("鼠标不支持写入....") 41 # 电脑--接口协议,传入以后按协议顺序执行 42 def pc(usb_device): 43 usb_device.open() 44 usb_device.read() 45 usb_device.write() 46 usb_device.close() 47 # 把鼠标传入电脑 48 m = Mouse() 49 # 调用鼠标 50 pc(m) 51 52 # 键盘 53 class KeyBoard(USB): 54 def open(self): 55 print("键盘开机.....") 56 57 def close(self): 58 print("键盘关机了...") 59 60 def read(self): 61 print("获取了按键字符....") 62 63 def write(self): 64 print("可以写入灯光颜色....") 65 66 67 # 来了一个键盘对象 68 k = KeyBoard() 69 pc(k) 70 71 # U盘 72 class UDisk(USB): 73 def open(self): 74 print("U盘启动了...") 75 76 def close(self): 77 print("U盘关闭了...") 78 79 def read(self): 80 print("读出数据") 81 82 def write(self): 83 print("写入数据") 84 85 u = UDisk() 86 pc(u) 87 88 """ 89 在上述案例中,PC的代码一旦完成,后期无论什么样的设备 只要遵循了USB接口协议,都能够被电脑所调用 90 91 接口主要是方便了对象的使用者,降低使用者的 学习难度,只要学习一套使用方法,就可以以不变应万变 92 93 问题: 94 95 如果子类没有按照你的协议来设计,也没办法限制他,将导致代码无法运行 96 97 解决:抽象类 98 """
2.抽象类.py
1 """""" 2 """ 3 抽象类: 4 指的是包含抽象方法(没有函数体的方法)的类 5 6 作用: 7 限制子类必须类中定义抽象方法 8 """ 9 """ 10 import abc 11 abc 是 单词abstract class(抽象类:类中包含没有函数体的方法) 的缩写 12 """ 13 import abc 14 class AClass(metaclass=abc.ABCMeta): 15 @abc.abstractmethod 16 def run(self): 17 pass 18 @abc.abstractmethod 19 def run1(self): 20 pass 21 # class B(AClass): 22 # 23 # def run(self): 24 # print("123455") 25 # b = B() 26 """ 27 报错: 28 Can‘t instantiate abstract class B with abstract methods run1 29 无法用抽象方法run1实例化抽象类B 30 31 """ 32 class B(AClass): 33 34 def run(self): 35 print("123455") 36 def run1(self): 37 print("4456554") 38 b = B() 39 b.run() # 123455 40 """ 41 结论: 42 抽象类,位继承类做了一个限制,如果不按照格式来,会报错 43 44 最后: 45 python一般不会限制你必须怎么写,作为一个优秀的程序员,就应该自觉遵守相关协议 46 47 所以有了鸭子类型这么一说: 48 """
3.鸭子类型--抽象类,优化.py
1 """""" 2 """ 3 鸭子类型: 4 如果这个对象长得像鸭子,走路像鸭子,那就他是鸭子 5 6 你只要保证你的类按照相关的协议类编写,也可以达到提高扩展性的目的 7 """ 8 # 鸭子类型 9 # 鼠标 10 class Mouse: 11 def open(self): 12 print("鼠标开机.....") 13 14 def close(self): 15 print("鼠标关机了...") 16 17 def read(self): 18 print("获取了光标位置....") 19 20 def write(self): 21 print("鼠标不支持写入....") 22 23 24 def pc(usb_device): 25 usb_device.open() 26 usb_device.read() 27 usb_device.write() 28 usb_device.close() 29 30 31 m = Mouse() 32 # 将鼠标传给电脑 33 pc(m) 34 35 36 class KeyBoard: 37 def open(self): 38 print("键盘开机.....") 39 40 def close(self): 41 print("键盘关机了...") 42 43 def read(self): 44 print("获取了按键字符....") 45 46 def write(self): 47 print("可以写入灯光颜色....") 48 49 50 # 来了一个键盘对象 51 k = KeyBoard() 52 pc(k) 53 54 55 class UDisk: 56 def open(self): 57 print("U盘启动了...") 58 59 def close(self): 60 print("U盘关闭了...") 61 62 def read(self): 63 print("读出数据") 64 65 def write(self): 66 print("写入数据") 67 68 69 u = UDisk() 70 pc(u)
4.总结.py
1 """""" 2 """ 3 接口 4 是一套协议规范,明确子类们应该具备哪些功能 5 6 抽象类 7 是用于强制要求子类必须按照协议中规定的来实现 8 9 鸭子类型: 10 然而,python不推崇限制你的语法, 我们可以设计成鸭子类型,既让多个不同类对象具备相同的属性和方法 11 12 对于使用者而言,就可以以不变应万变,轻松的使用各种对象 13 """
以上是关于封装- --接口,抽象, 鸭子类型 #22的主要内容,如果未能解决你的问题,请参考以下文章