zoukankan      html  css  js  c++  java
  • 对象的封装与接口

    一.对象的封装

    什么是封装:对外隐藏内部实现细节,并提供访问的接口

    封装的目的:

    ​ 1.为了保证 关键数据的安全性

    ​ 2.对外部隐藏实现细节,隔离复杂度

    什么时候应该封装:

    当有一些数据不希望外界可以直接修改时

    ​ 当有一些函数不希望给外界使用时,

     如何封装:

    class Person:
            def __init__(self,id_number,name,age)
            self.__id_number = id_number
            # 比如这里是比较重要的身份证号码,不能随便调用
            # 给属性或者方法前面加上 __   
            def show_id(self):
               print(self.__id_number)
    
            def __say_hi(self):
               print(f"hi, 我是{self.name}")
    
    
    p = Person('35676549809711', 'bitten', 29)
    p.id_number = '3756789'  # 这里其实是给对象加了个属性 id_number(对象属性的增删改查)
    print(p.id_number)
    # 3756789
    p.show_id()
    # 35676549809711  # 并没有受到影响
    # p.__id_number  # 报错,pycharm没有提示也找不到,AttributeError: 'Person' object has no attribute '__id_number'
    # p.__say_hi  # 报错,AttributeError: 'Person' object has no attribute '__say_hi'双下划线,外界就访问不到了
            self.name = name
            self.age = age
       
    p = Person("35676549809711","bitten",29)
    
    p.id_number = "222"
    View Code

    被封装内容的特点:

    1.外界不能直接访问

    ​ 2.内部依然可以使用

    封装可以控制属性的权限

    python的两种权限:

    1.公开的.默认就是公开的

    2.私有的,只能由当前类自己使用

    外界访问私有内容:通过定义方法类可以完成在外部对私有属性的修改和访问

    """
    这是一个下载器类,需要提供一个缓存大小这样的属性
    缓存大小不能超过内存限制
    
    """
    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.baicu.com",1024*1024)
    
    
    # 通过函数取修改内部封装的属性
    d.set_buffer_size(1024*512)
    
    # 通过函数访问内部封装的属性
    print(d.get_buffer_size())
    
    d.start_download()
    View Code

    语法:将要封装的属性或方法名称前加上双下划线

    访问被隐藏的属性:

    ​提供用于访问和修改的方法

    使用property装饰器可以将一个方法伪装成普通顺属性,让属性之间调用方法一致

    封装的实现原理 ,替换变量名称

    二.装饰器

    property装饰就是为了使普通属性和私有属性得调用方式一致

    1.property 该装器用在获取属性的方法上
    2.@key.setter 该装饰器用在修改属性的方法上
    3.@key.deleter 该装饰器用在删除属性的方法上

    注意:key是被property装饰的方法的名称 也就是属性的名称
    内部会创建一个对象 变量名称就是函数名称
    所以在使用setter和deleter时 必须保证使用对象的名称取调用方法
    所以是 key.setter
    ```

    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
            
    a = A("jack",123)
    print(a.key)
    a.key = 321
    print(a.key)
    View Code

    python实现封装的原理

    就是在加载类的时候,把_ _替换成了 _类名_ _

    python一般不会强制要求程序必须怎么怎么的,

    property 实现计算属性

    计算属性指的是:属性的值,不能直接获得,必须通过计算才能获取

    例如:正方形求面积

    class Square:  # 正方形
    
        def __init__(self, width):
            self.width = width
            self.area = self.width * self.width
    
    
    s = Square(10)
    print(s.area)
    # 100
    
    s.width = 20
    print(s.area)  # 后续更改了width,它的值就不对了
    # 100
    
    
    class Square2:  # 正方形
    
        def __init__(self, width):
            self.width = width
            # self.area = self.width * self.width  # 下面定义的时候要把这里去掉
    
        @property  # 只要 . 这个属性, 就会自动触发这个函数
        def area(self):
            return self.width * self.width
    
    
    s2 = Square2(10)
    print(s2.area)
    # 100
    
    s2.width = 20
    print(s2.area)
    # 400
    View Code

    三.接口

    接口是一组功能的集合,但是接口中仅包含功能的名字,不包含具体的实现代码

    接口本质是一套协议标准,遵循这个标准的对象就能被调用

    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)
    View Code

    接口目的:提高扩展性:

    四.抽象类

    抽象类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("runrunrurn...")
    
    b = B()
    View Code

    抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化,且子类必须实现抽象方法

    作用:可以限制子类必须类中定义的抽象方法  

    接口是一套协议规范,明确子类们应该具备哪些功能。

    抽象类是用于强制要求子类必须按照协议中规定的来实现

    然而,python不推崇使用抽象类限制语法。

    默认设计成鸭子类型,既让多个不同类对象具备相同的属性和方法

    对于使用者而言,就可以以不变应万变,轻松的使用各种对象

    #默认用鸭子类型
    class Mouse:
        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:
        def open(self):
            print("键盘开机.....")
    
        def close(self):
            print("键盘关机了...")
            
        def read(self):
            print("获取了按键字符....")
            
        def write(self):
            print("可以写入灯光颜色....")
    
            
    # 来了一个键盘对象
    k = KeyBoard()
    pc(k)
    
    class UDisk:
        def open(self):
            print("U盘启动了...")
    
        def close(self):
            print("U盘关闭了...")
    
        def read(self):
            print("读出数据")
    
        def write(self):
            print("写入数据")
    
    u = UDisk()
    pc(u)
    View Code
  • 相关阅读:
    网络七层
    微信小程序开发工具 常用快捷键
    BZOJ 1026 windy数 (数位DP)
    BZOJ 1026 windy数 (数位DP)
    CodeForces 55D Beautiful numbers (SPOJ JZPEXT 数位DP)
    CodeForces 55D Beautiful numbers (SPOJ JZPEXT 数位DP)
    HDU 3709 Balanced Number (数位DP)
    HDU 3709 Balanced Number (数位DP)
    UVA 11361 Investigating Div-Sum Property (数位DP)
    UVA 11361 Investigating Div-Sum Property (数位DP)
  • 原文地址:https://www.cnblogs.com/Cpsyche/p/11261140.html
Copyright © 2011-2022 走看看