封装- --接口,抽象, 鸭子类型 #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
1.封装
    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 """
2.封装方法
    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 """
3.如何访问被封装的属性
    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)
4.property装饰器
    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
5.封装的原理
    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)
6.计算属性,实际应用
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 """
1.接口--定义一个接口类
    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 """
2.抽象类--abc模块(要求必须按照协议,否则会报错)
    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)
3.鸭子类型(使用已存在的类,提高扩展性)
    4.总结.py
技术图片
 1 """"""
 2 """
 3 接口
 4     是一套协议规范,明确子类们应该具备哪些功能
 5 
 6 抽象类
 7     是用于强制要求子类必须按照协议中规定的来实现  
 8 
 9 鸭子类型:
10     然而,python不推崇限制你的语法, 我们可以设计成鸭子类型,既让多个不同类对象具备相同的属性和方法
11 
12 对于使用者而言,就可以以不变应万变,轻松的使用各种对象 
13 """
4.总结 接口,抽象类,鸭子类型

 

以上是关于封装- --接口,抽象, 鸭子类型 #22的主要内容,如果未能解决你的问题,请参考以下文章

026 面向对象05——封装

多态/封装

Day21 抽象接口多太鸭子类型

关于python鸭子类型和白鹅类型

鸭子类型-类的约束-异常处理

python之类的多态(鸭子类型 )封装和内置函数property