知识点 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_number43 self.name = name44 self.age = age45 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) # 111150 # __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 检测硬件133 检测硬件234 检测硬件335 检测硬件436 载入内核37 初始化内核38 启动GUI39 启动服务140 启动服务241 启动服务342 启动服务443 login....44 login....45 login....46 """47 48 """封装方法"""49 """ 语法 : __名称(双下划綫+类属性(初始化值)或方法(函数名))"""50 class PC:51 def __init__(self,price,kind,color):52 self.price = price53 self.kind = kind54 self.color = color55 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 检测硬件184 检测硬件285 检测硬件386 检测硬件487 载入内核88 初始化内核89 启动服务190 启动服务291 启动服务392 启动服务493 启动GUI94 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 = filename19 self.url = url20 self.__buffer_size = buffer_size21 # 缓存大小不能超过内存大小22 def start_download(self):23 # 内存大小:1024*102424 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 = size36 else:37 print('大哥,缓存区大小必须是整型')38 # 获取缓存区大小39 def get_buffer_size(self):40 return self.__buffer_size41 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 419430457 内存炸了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.setter23 """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 = filename40 self.url = url41 self.__buffer_size = buffer_size42 43 # 获取缓存区大小44 @property45 def buffer_size(self):46 return self.__buffer_size47 # 缓存大小不能超过内存大小48 49 @buffer_size.deleter50 def buffer_size(self):51 print("不允许删除该属性")52 del self.__buffer_size53 # 设置(修改)缓存大小54 # 一额外逻辑55 @buffer_size.setter56 def buffer_size(self,size):57 # 缓存大小必须是整型58 if type(size) == int:59 print('缓存区大小修改成功')60 self.__buffer_size = size61 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*209680 # print(p.buffer_size)81 # 删82 del p.buffer_size83 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 = key25 26 # 获取方法27 @property28 def key(self):29 return self.__key30 # 修改方法31 @key.setter32 def key(self,re_key):33 self.__key = re_key34 return self.__key35 # 删除方法36 @key.deleter37 def key(self):38 del self.__key39 p = A('assd')40 # 获取方法41 #print(p.key) # assd42 # 修改方法43 # p.key = 'gfghfhjgg'44 # print(p.key) # gfghfhjgg45 # # 删除方法46 # del p.key47 print(p._A__key) # assd48 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 = width16 # 获取正方形的面积17 @property18 def area(self):19 return self.width * self.width20 @area.setter21 def area(self,number):22 self.width = number23 return self.width24 @area.deleter25 def area(self):26 del self.width27 28 p = Square(5)29 print(p.area)30 p.width = 1031 print(p.area)32 # 案例二33 # 练习: 定义一个类叫做person34 # 包含三个属性 身高 体重 BMI35 # BMI的值需要通过计算得来 公式 体重 / 身高的平方36 class Person:37 def __init__(self,high,weigh):38 self.high = high39 self.weigh = weigh40 @property41 def BMI(self):42 return self.weigh / self.high / self.high43 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 pass22 def close(self):23 pass24 def read(self):25 pass26 def write(self):27 pass28 # 鼠标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 abc11 abc 是 单词abstract class(抽象类:类中包含没有函数体的方法) 的缩写12 """13 import abc14 class AClass(metaclass=abc.ABCMeta):15 @abc.abstractmethod16 def run(self):17 pass18 @abc.abstractmethod19 def run1(self):20 pass21 # 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 run129 无法用抽象方法run1实例化抽象类B30 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() # 12345540 """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 """