22.封装 property装饰器 接口 抽象类 鸭子类型
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1.封装 2.好处 3.语法 4.原理 5.访问私有属性的方法 property装饰器 6.计算属性 7.接口 8.抽象类 9.鸭子类型 1.封装: 什么是封装,就是将复杂的丑陋的,隐私的细节隐藏到内部,对外提供简单的使用接口 对外隐藏内部实现细节,并提供访问的接口 为什么要封装? 两个目的: 1.为了保证 关键数据的安全性 2.对外部隐藏实现细节,隔离复杂度 什么时候应该封装? 当有些数据不希望外界可以直接修改时, 当有一些函数不希望给外界使用时 如何使用 ? __封装对象 - 1.封装的基本使用.py 被封装内容的特点: 1.外部不能直接访问 2.内部依然可以使用 学习了封装后就可以控制属性的权限 在python只要两种权限, 1.公开的.默认就是公开的 2.私有的,只能由当前类自己使用 在外界访问私有的内容 属性虽然被封装了,但是还是需要使用的,在外界如何访问 通过定义方法类完成对私有属性的修改和访问 3.如何访问被封装的属性.py ``` 这样一来我们可以在外界修改这个关键数据时,做一些限制 4.property装饰器 通过方法来修改或访问属性,本身没什么问题,但是这给对象的使用者带来了麻烦. 使用必须知道哪些是普通属性,哪些是私有属性,需要使用不同的方式来调用他们 property装饰就是为了使得调用方式一致 property 三个相关装饰器 1.property 该装饰器用于获取属性的方法上 2.@key.setter 该装饰器用在修改属性的方法上 3.@key.deleter 该装饰器用于删除属性的方法上 ps: key 是被property 装饰的方法名称,也就是属性的名称 内部会创建一个对象,变量名称就是函数名称 所以在使用setter 和 deleter时,必须保证使用对象的名称去调用方法. 所以是 key.setter 4.property装饰器.py 5.封装实现的原理 就是在加载类的时候 ,把__替换成 _类名__ Python 一般 不会强制 要求程序必须 怎么怎么的 封装 对外部隐藏内部实现的细节,并提供访问的接口 好处: 1.提高安全性 2.隔离复杂度 语法:将要封装的属性或方法名称前加上双下划线 访问被隐藏的属性: 提供用于访问和修改的方法 使用property装饰器可以将一个方法伪装成普通顺属性,报纸属性之间调用方法一致 封装的实现原理 ,替换变量名称 6.property 可以用来实现计算属性 计算属性指的是:属性的值,不能直接获得,必须通过计算才能获取 例如:正方形求面积 6.计算属性.py 7.接口 接口是一组功能的集合体,但是接口中仅仅包含功能的名字,不包含具体的实现代码 接口的本质:一套协议标准,遵循这个标准的对象就可以被调用 接口的目的: 就是为了提高扩展性 例: 7.接口的使用.py 在上述案例中,PC的代码一旦完成,后期无论什么样的设备 只要遵循了USB接口协议,都能够被电脑所调用 接口主要是方便了对象的使用者,降低使用者的 学习难度,只要学习一套使用方法,就可以以不变应万变 问题: 如果子类没有按照你的协议来设计,也没办法限制他,将导致代码无法运行 8.抽象类 指的是包含抽象方法(没有函数体的方法)的类, 作用:可以限制子类必须类中定义的抽象方法 最后:python一般不会限制你必须怎么写,作为一个优秀的程序员,就应该自觉遵守相关协议 所以有了鸭子类型这么一说: 如果这个对象长得像鸭子,走路像鸭子,那就他是鸭子 你只要保证你的类按照相关的协议类编写,也可以达到提高扩展性的目的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Person: def __init__(self,id_number,name,age): self.__id_number = id_number self.name = name self.age = age def show_id(self): print(self.__id_number) p = Person("111111111",'jack',29) p.__id_number = "222" # print(p.__id_number) print(p.show_id()) """ 111111111 None """
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class PC: def __init__(self,price,kind,color): self.price = price self.kind = kind self.color = color def open(self): print("接通电源") self.__check_device() print("载入内核") self.__start_services() print("初始化内核") self.__login() print("启动GUI") def __check_device(self): print("硬件检测1") print("硬件检测2") print("硬件检测3") print("硬件检测4") def __start_services(self): print("启动服务1") print("启动服务2") print("启动服务3") print("启动服务4") def __login(self): print("login....") print("login....") print("login....") pc1 = PC(20000,'苹果',"红色") pc1.open() # pc1.login() """ 接通电源 硬件检测1 硬件检测2 硬件检测3 硬件检测4 载入内核 启动服务1 启动服务2 启动服务3 启动服务4 初始化内核 login.... login.... login.... 启动GUI """
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
""" 这是一个下载器类,需要提供一个缓存大小这样的属性 缓存大小不能超过内存限制 """ 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("当前缓冲器大小",self.__buffer_size) else: print("内存炸了") def set_buffer_size(self,size): # 可以在方法中添加额外的逻辑 if not type(size) == int: print("大哥,缓冲区大小必须是整型") else: print("缓冲器大小修改成功") 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*512) # 通过函数访问内部封装的属性 print(d.get_buffer_size()) print(d.filename) d.start_download() """ 缓冲器大小修改成功 524288 葫芦娃 开始下载.... 当前缓冲器大小 524288 """
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name,key): self.__name = name self.__key = key @property def key(self): return self.__key @key.setter def key(self,new_key): if new_key <= 100: self.__key = new_key else: print("key 必须小于等于100") @key.deleter def key(self): print("不允许删除该属性") del self.__key # @property # def name(self): # return self.__name # # @name.setter # def name(self, new_name): # self.__name = new_name a = A('jack',123) # print(a.name) print(a.key) # 123 a.key = 321 # key 必须小于等于100 print(a.key) # 123 # del a.key # print(a.key) a.name = "xx" print(a.name) # xx
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,key): self.__key = key @property def key(self): return self.__key @key.deleter def key(self): del self.__key a = A("123") print(a.key) # 123 # del a.key # print(a.key) print(a._A__key)# 123 a.__name = 1 print(a.__dict__) # {'_A__key': '123', '__name': 1} print("__key".replace("__","_A__")) # _A__key
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Square: def __init__(self,width): self.width = width # self.area = self.width * self.width @property def area(self): return self.width * self.width s = Square(10) print(s.area) # # 练习: 定义一个类叫做person # 包含三个属性 身高 体重 BMI # BMI的值需要通过计算得来 公式 体重 / 身高的平方 class Person: def __init__(self,high,wight): self.high = high self.wight = wight @property def BMI(self): return self.wight / (self.high ** 2) p = Person(180,85) print(p.BMI)# 0.002623456790123457
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class USB: def open(self): pass def close(self): pass def read(self): pass def write(self): pass class Mouse(USB): def open(self): print("鼠标开机.....") def close(self): print("鼠标关机了...") def read(self): print("获取了光标位置....") def write(self): print("鼠标不支持写入....") def pc(usb_device): usb_device.open() usb_device.read() usb_device.write() usb_device.close() m = Mouse() # 将鼠标传给电脑 pc(m) class KeyBoard(USB): def open(self): print("键盘开机.....") def close(self): print("键盘关机了...") def read(self): print("获取了按键字符....") def write(self): print("可以写入灯光颜色....") # 来了一个键盘对象 k = KeyBoard() pc(k) class UDisk(USB): def open(self): print("U盘启动了...") def close(self): print("U盘关闭了...") def read(self): print("读出数据") def write(self): print("写入数据") u = UDisk() pc(u)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
"""""" """ abc 不是随意取的 而是单词的缩写 abstract class 翻译为抽象类 抽象类的定义 : 类中包含 没有函数体的方法 """ import abc class AClass(metaclass=abc.ABCMeta): @abc.abstractmethod def run(self): pass @abc.abstractmethod def run1(self): pass class B(AClass): def run(self): print("runnnnnnnn....") def run1(self): print("run111111") b = B() print(b.run) """ <bound method B.run of <__main__.B object at 0x0000025B2DB25438>> """