zoukankan      html  css  js  c++  java
  • OPP三大特性之封装

    一、封装的基本知识

    1.什么是封装

    封装就是将复杂丑陋,隐私的细节隐藏到内部,对外提供简单的使用接口

    对外隐藏内部实现细节,并提供访问的接口

    2.为什么要封装

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

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

    3.什么时候应该封装

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

    2.当一些函数不希望外界使用时

    4.如何使用

    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('111','jack',18)
    p.__id_number = '222'  # 将id_number进行封装,用222来掩饰111
    print(p.__id_number)  # 打印的值:222
    
    p.show_id()  # 111

    二、如何访问被封装的属性

    属性虽然被封装了,但是还是需要使用的,

    在外界如何定义类完成对私有属性的修改和访问

     

    练习:
    这是一个下载器类,需要提供一个缓存大小这样的属性
    缓存大小不能超过内存限制
    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()')
    
    d.start_download() 
    #打印结果 缓存器大小修改成功 d.get_buffer_size() 开始下载... 当前缓存器大小 1048576 #这样就可以在外界修改这个关键数据时,做一些限制

    三、property装饰器

    通过方法来修改或访问属性,本身没什么问题,但是却给对象的使用者带来了麻烦.

    使用者必须知道哪些是普通属性,哪些是私有属性,需要使用不同的方法来调用它们,

    property装饰器能够让调用方式一致

     

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

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

     

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


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

     

    1.@property

    # property获取属性
    class A:
        def __init__(self,name,key):
            self.name = name
            self.__key = key
    
        def get_key(self):
            return self.__key
    
        def set_key(self,new_key):
            self.__key = new_key
    
        @property  # 查找属性
        def key(self):
            return self.__key
    
    a = A('jack',123)
    print(a.name)
    print(a.key)

    2.@key.setter

    class A:
        def __init__(self,name,key):
            self.name = name
            self.__key = key
    
        def get_key(self):
            return self.__key
    
    
        def set_key(self,new_key):
            self.__key = new_key
    
    
        @property
        def key(self):
            return self.__key
    
    
        @key.setter  # 修改属性
        def key(self,new_key):
            self.__key = new_key
    
    
    a = A('jack',123)
    print(a.name)
    
    
    a.key = 456  # 修改为456
    print(a.key)

    3.@deleter

    class A:
        def __init__(self,name,key):
            self.name = name
            self.__key = key
    
        def get_key(self):
            return self.__key
    
    
        def set_key(self,new_key):
            self.__key = new_key
    
    
        @property
        def key(self):
            return self.__key
    
    
        @key.setter  # 修改属性
        def key(self,new_key):
            self.__key = new_key
        @key.deleter  # 删除属性
        def key(self):
            print('run')  
    
    
    
    a = A('jack',123)
    # print(a.name)
    #
    #
    # a.key = 456  # 修改为456
    # print(a.key)
    del a.key
    
    #打印结果显示:run 成功删除

    四、python实现封装的原理

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

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

    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
    # print(a.__dict__)  # {'_A__key': '123'}
    
    print(a._A__key)  # 123

    五、property 可以用来实现计算属性

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

    例如:正方形求面积

    class Square:
    
        def __init__(self,width):
            self.width = width
           
    
        @property
        def area(self):
            return self.width * self.width
    
    s = Square(10)
    
    print(s.area)  # 100

    六、接口

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

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

     

    接口目的就是为了提高扩展性:

    例如电脑提前指定制定一套USB接口协议,只要你遵循该协议,你的设备就可以被电脑使用,不需要关心到底是鼠标还是键盘

     

    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盘不能读取数据,所以最后赢得打印结果会报错
    
    u = UDisk()
    
    pc(u)

    七、抽象类

    指的是包含抽象方法(没有函数体的方法)的类,

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

     

    最后:python一般不会限制你必须怎么写,作为一个优秀的程序员,就应该自觉遵守相关协议

    所以有了鸭子类型这么一说:

    如果这个对象长得像鸭子,走路像鸭子,那就他是鸭子

    你只要保证你的类按照相关的协议类编写,也可以达到提高扩展性的目的

     




  • 相关阅读:
    leetcode 155. Min Stack 、232. Implement Queue using Stacks 、225. Implement Stack using Queues
    leetcode 557. Reverse Words in a String III 、151. Reverse Words in a String
    leetcode 153. Find Minimum in Rotated Sorted Array 、154. Find Minimum in Rotated Sorted Array II 、33. Search in Rotated Sorted Array 、81. Search in Rotated Sorted Array II 、704. Binary Search
    leetcode 344. Reverse String 、541. Reverse String II 、796. Rotate String
    leetcode 162. Find Peak Element
    leetcode 88. Merge Sorted Array
    leetcode 74. Search a 2D Matrix 、240. Search a 2D Matrix II
    Android的API版本和名称对应关系
    spring 定时任务执行两次解决办法
    解析字符串为泛型的方法
  • 原文地址:https://www.cnblogs.com/xiongying4/p/11253370.html
Copyright © 2011-2022 走看看