zoukankan      html  css  js  c++  java
  • 上海 day22 -- 面向对象三大特征---- 封装

    目  录

    一、封装

    什么是封装?

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

    为什么需要封装?

    两个目的:1、保证关键数据的安全性;2、隐藏内部的实现细节,隔离复杂度。

    什么时候需要封装?

    当有一些数据不需要被外界直接修改时;

    当有的函数不希望被外界使用的时候。

    二、封装的使用

     封装的语法:

    将要封装的属性或方法名称前加双下划线' __ '

    代码示例:封装属性

    class Person:
        def __init__(self,id,name,age):
            self.__id = id
            self.name = name
            self.age = age
    
        def show_id(self):
            print(self.__id)
    p1 = Person('1234','jason',24)
    p1.show_id()  # 1234
    
    print(p1.__id)  # AttributeError: 'Person' object has no attribute '__id' 外界无法访问

    代码示例:封装方法

    '''
    封装方法
    '''
    class PC:
        def __init__(self,kind,price,color):
            self.kind = kind
            self.price = price
            self.color = color
    
        def open(self):
            print('接通电源。。')
            self.__check_divice()  # 只能在类的内部调用,也只有在内部才能访问的到
            print('载入内核。。')
            print('初始化内核。。')
            self.__start_services()
            print('启动GUI。。')
            self.__login()
    
        def __check_divice(self):
            print('检测硬件1')
            print('检测硬件2')
            print('检测硬件3')
            print('检测硬件4')
    
        def __start_services(self):
            print('开启服务1。。')
            print('开启服务2。。')
            print('开启服务3。。')
            print('开启服务4。。')
    
        def __login(self):
            print('开始登陆。。')
            print('开始登陆。。')
            print('开始登陆。。')
            print('开始登陆。。')
    pc1 = PC('Thinkpad',2000,'red')
    pc1.open()
    pc1.__check_divice()  # AttributeError: 'PC' object has no attribute '__check_divice'
    封装方法

    被封装的内容有什么特点?

    1、外部不能直接访问

    2、内部依然可以调用

    控制属性的权限?

    在Python中只有两种权限:

    1、公开的,默认是公开的

    2、私有的,只能在当前类中使用

    三、外界访问私有的内容

    属性虽然被封装了,但是还是需要使用的,在外界如何访问

    通过在类内部定义方法完成对私有属性的修改和访问

    '''
    外部访问私有内容
    '''
    class Downer:
        def __init__(self, file_name, url, down_size):
            self.file_name = file_name
            self.url = url
            self.__down_size = down_size
    
        def download(self):
            if self.__down_size >= 1024*1024:
                print('开始下载。。。')
                print('当前缓冲器大小。。%s'%self.__down_size)
            else:
                print('内存炸了!')
    
        def set_size(self,size):
            if not type(size) == int:
                print('缓冲必须是整型才可以')
            else:
                print('缓冲区修改成功!')
                self.__down_size = size  #  定义方法修改 私有属性 __down_size
    
        def get_size(self):
            return self.__down_size  #  定义方法访问私有属性  __down_size
    
    d1 = Downer('xunlei','http://www.coming',1024*1024)
    d1.download()
    # print(d1.get_size())
    d1.set_size(1024*2000)  # 2048000  修改私有属性
    d1.download()
    print(d1.get_size())  # 2048000  访问已经修改的私有属性

    这样一来我们可以在外界修改这个关键数据时,做一些限制

    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,size):
            if size > 100:   # 可以设置逻辑判断来选择性设置私有属性
                print('太大了')
            else:
                self.__key = size
    
        @key.deleter
        def key(self):
            print('你就是删除不了')
            del self.__key
    
    a = A('tank','59')
    # print(a.key)  # 这样设置就和普通的对象属性一样,通过 对象名.属性  来访问私有属性
    a.key = 99
    print(a.key)
    a.name = 'jaosn'
    print(a.name)

    property 可以用来计算属性

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

    例如:正方形求面积

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

     

    四、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
    
    a1 = A('123')
    # del a1.key
    # print(a1.key)
    # 通过__dict__方法访问a1的名称空间
    print(a1.__dict__)  # {'_A__key': '123'} 封装的原理是将 __key 改为 _A__key
    print(a1._A__key)  # 123 通过该方法获得 123
    
    
    # 由以上代码可知,我们访问不到私有属性的原因是,类内部将私有属性的名字改掉了

     五、接口与抽象类

    1、接口

    什么是接口?

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

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

    接口有什么功能?

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

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

    案例:

    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

    在上述案例中,PC的代码一旦完成,后期无论什么样的设备 只要遵循了USB接口协议,都能够被电脑所调用

    接口主要是方便了对象的使用者,降低使用者的 学习难度,只要学习一套使用方法,就可以以不变应万变

    问题?——》引出抽象类

    如果子类没有按照你的协议来设计,也没办法限制他,将导致代码无法运行

    2、抽象类

    什么是抽象类?

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

    抽象类有什么作用?

    可以限制子类必须具备父类中定义的抽象方法

    abc模块的使用:

    """
    abc 不是随意取的 而是单词的缩写
    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()

    最后总结:鸭子类型

    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)
    鸭子类型

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

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

    然而,python不推崇限制你的语法, 我们可以设计成鸭子类型,既让多个不同类对象具备相同的属性和方法

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

     

     

     

     

     

  • 相关阅读:
    阿里安全称发现安卓WiFi漏洞:黑客可远程攻击
    Android Art Hook 技术方案
    java 静态代码块执行顺序
    sqlzoo易错题
    Centos7安装配置Nginx_笔记
    System.Runtime.Caching中MemoryCache帮助类
    youtube-dl工具的使用
    C#程序员快速上手Angular开发
    npm常见配置收集
    Resharp常用设置收集整理
  • 原文地址:https://www.cnblogs.com/qinsungui921112/p/11252060.html
Copyright © 2011-2022 走看看