zoukankan      html  css  js  c++  java
  • 封装- --接口,抽象, 鸭子类型 #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.总结 接口,抽象类,鸭子类型
  • 相关阅读:
    洛谷 P1567 统计天数【最长上升子序列/断则归一】
    洛谷 P3742 umi的函数【构造】
    洛谷 P1036 选数【背包型DFS/选or不选】
    nyoj zb的生日【背包型DFS/选or不选】
    POJ 3628 Bookshelf 2【背包型DFS/选or不选】
    【AHOI2013复仇】从一道题来看DFS及其优化的一般步骤和数组分层问题【转】
    洛谷 P1217 [USACO1.5]回文质数 Prime Palindromes【取回文数/数论/字符串】
    洛谷 P1004 方格取数 【多线程DP/四维DP/】
    Codeforces Round #449 (Div. 2) B. Chtholly's request【偶数位回文数】
    Codeforces Round #449 (Div. 2) A. Scarborough Fair【多次区间修改字符串】
  • 原文地址:https://www.cnblogs.com/llx--20190411/p/11259961.html
Copyright © 2011-2022 走看看