zoukankan      html  css  js  c++  java
  • python26 1 封装 2多态 3常用的内置函数 `__str__` `__del__` 4反射 5动态导入模块

     
    今日内容:
     
    1. 封装   
    2.多态
    3. 常用的内置函数  
    `__str__
    `__del__`
    4.反射
    5.动态导入模块 
     
    #1. 封装
    ##1.1 什么是封装 ?(what)
             对外部隐藏内部的属性,以及实现细节  , 给外部提供使用的接口
    注意:封装有隐藏的意思,但不是单纯的隐藏
    1.2学习封装的目的.
                        就是为了能够限制外界对内部数据的访问
    1.3python中属性的权限分为两种
              1.公开的
    ​           没有任何限制 谁都能访问
              2.私有的
    ​          只有当前类本身能够访问
    注:默认为公共的
     
    1.4## 如何封装 ?(how)
    ......一个为内部提供支持的方法,不应该让外界直接访问,那就封装起来 ,如下例中的 user_auth等..............
     
    1.5## 为什么要封装?( why)
     
    ​      封装属性----> 1.提高安全性 
    ​     
          封装方法 ---->2.隔离复杂度  
     
     案例说明:
           一个类中分为两种数据,属性和方法
         1.5.1 # 封装属性:(是一种对类中初始化函数中参数的封装)
    ```             需要重新以此参数 建立一个新的函数,可以在这里添加额外的任何逻辑代码 来限制外部的访问
            1 #在类的内部 可以访问    2 # 访问被封装的属性  称之为访问器    3# 修改被封装的属性   称之为设置器
    class Student:
        def __init__(self,name,age,gender,id_card):
            self.name = name
            self.age = age
            self.gender = gender
            self.__id_card = id_card
        def show_id_card(self):
            # 可以在这里添加额外的任何逻辑代码 来限制外部的访问
           
            #在类的内部 可以访问
            print(self.__id_card)
    ```
    #对私有属性的访问以及修改
         1 # 访问被封装的属性  称之为访问器    2# 修改被封装的属性   称之为设置器   
    ```
    class Student:
        def __init__(self,name,age,gender,id_card):
            self.name = name
            self.age = age
            self.gender = gender
            self.__id_card = id_card
        # 访问被封装的属性  称之为访问器
        def get_id_card(self,pwd):
            # 可以在这里添加额外的任何逻辑代码 来限制外部的访问
            # 在类的内部 可以访问
            if pwd =="123":
                return self.__id_card
            raise Exception("密码错误!")

        # 修改被封装的属性   称之为设置器
        def set_id_crad(self,new_id):
            # 身份证必须是字符串类型
            # 长度必须是18位
            if isinstance(new_id,str) and len(new_id) == 18:
                self.__id_card = new_id
            else:
                raise Exception("身份证号码 必须是字符串 且长度必须为18!")
    ```
    1.5.2封装方法
    什么样的方法应该被封装起来
    ​ 一个为内部提供支持的方法,不应该让外界直接访问,那就封装起来 ,如下例中的 user_auth等...
    ```
    class ATM:
        def withdraw(self):
            self.__user_auth()
            self.__input_money()
            self.__save_record()
            # 输入账号和密码
            # 显示余额
            # 输入取款金额
            # 保存记录
        def __user_auth(self):
            print("请输入账号密码....")
        def __input_money(self):
            print("余额为100000000,请输入取款金额!")
        def  __save_record(self):
            print("记录流水....")
    ```
    1.6封装的原理:
    ```
    python是通过 变形的方式来实现的封装
    如何变形 在名称带有双下划线开头的变量名字前添加_类名  如_Person__id_card
    当然通过变形后的名字可以直接访问被隐藏的属性  但通过不应该这么做
    变形仅在类的定义阶段发生一次 后续再添加的带有双下划线的任何属性都不会变形  就是普通属性
    ```
     
    1.7什么时候用?( where)
     
       1.7.1封装属性  
    ​ 当这个对象存在一个机密性的属性  例如 人的身份证 银行卡密码等等,这样属性不应该被外界直接 访问当 ,那就封装起来
    Person  密码    Teacher  工资   
       1.7.2封装方法  
    ​ 一个为内部提供支持的方法,不应该让外界直接访问,那就封装起来 ,如下例中的 user_auth等..
     
    1.8封装属性调用方法与普通属性的区别
           1.8.1 原因:
                       被封装的属性在访问时需要调用方法 ,而普通的属性直接'.'(点)就OK了,这样以来对于使用者而言,就必须知道要访问的属性,是私有的还               是公有的,然后调用对应的方法,用起来比就麻烦。未解决此时就涉及到Property的使用
            1.8.2Property
                       作用: 将一个方法伪装成普通属性
    为什么用 property   ?
                      希望将访问私有属性和普通属性的方式变得一致
    与property相关的 两个装饰器 ?
                    setter
    ​                用点语法 给属性赋值时触发  
                     deleter
    ​                 用点语法删除属性时触发
    案例:
    @property  # getter   # 用于访问私有属性的值   也可以访问普通属性
    @salary.setter   # 用来设置私有属性的值  也可以设置普通属性
    @salary.deleter # 用来设置私有属性的值  也可以删除普通属性
    ```
    class Teacher:
        def __init__(self,name,age,salary):
            self.name = name
            self.age = age
            self.__salary = salary
        @property  # getter   # 用于访问私有属性的值   也可以访问普通属性
        def salary(self):
            return self.__salary
        @salary.setter   # 用来设置私有属性的值  也可以设置普通属性
        def salary(self,new_salary):
            self.__salary = new_salary
        @salary.deleter # 用来设置私有属性的值  也可以删除普通属性
        def salary(self):
            # print("can not delete salary!")
            del self.__dict__["_Teacher__salary"]
    ```
     
    1.8.3## property的另一种使用场景  计算属性
                  什么是计算属性   一个属性 它的值不是固定死的 而是通过计算动态产生的
             BMI
    ```
    class Person:
        def __init__(self,name,height,weight):
            self.name = name
            self.height = height
            self.weight = weight
            # self.BMI = weight / (height ** 2)
        @property
        def BMI(self):
            return self.weight / (self.height ** 2)
        @BMI.setter
        def BMI(self,new_BMI):
            print("BMI 不支持自定义.....")

    p = Person("egon",1.7,80)
    print(p.BMI)
    p.BMI = 10
    ```
    2.多态 :
        2.1定义:
              多态不是一个具体的技术  或代码
               指的是 多个不同类型对象 可以响应同一个方法 ,产生不同结果 
    ```
        2.2 多态(现实描述)
               某种事物具备多个不同形态
               例如 水:   气态  固态  液态
               动物: 人  猫  猪
               汽车人:  汽车 飞机  人型
    面向对象中的标准解释:
         OOP中 标准解释: 多个不同类型对象 可以响应同一个方法  并且产生不同结果
     
    2.3多态的带来的好处:
        只需要学习基类中的使用方法即可, 不需要关心具体的哪一个类 以及实现的   以不变应万变  
             1.提高了灵活性
             2.提高扩展性
    2.4多态存在的意义:    
        如果没有多态  需要分别学习 person  cat pig 的不同使用方法 这对于使用者而言太麻烦了
    2.5 如何实现多态:
          鸭子类型 就是典型的多态 多种不同类型 使用方法一样
    ```
    ## 案例:说明:
    # 一个用来管理动物的方法   只要你传入是一个动物 我就按照动物的标准来使用 完全不用考虑你具体是什么类型
    ```
    class Cat():
        def bark(self):
            print("喵喵喵")
        def run(self):
            print("四条腿跑!")
        def sleep(self):
            print("趴着睡!")
           
    class Pig():
        def bark(self):
            print("哼哼哼!")
        def run(self):
            print("四条腿跑!")
        def sleep(self):
            print("侧躺着睡!")
    # 一个用来管理动物的方法   只要你传入是一个动物 我就按照动物的标准来使用 完全不用考虑你具体是什么类型
    def management_animal(animal):
        print("==================正在溜%s=============" % animal.__class__.__name__)
        animal.bark()
        animal.run()
        animal.sleep()
    ``'
     
    3.# 常用的内置函数
     
                             1. `__str__`
     
                             2.  `__del__`
    ```
    3.1`__str__`
    类中的__str__
       该方法在object中有定义 默认行为 返回对象类型以及地址   ------   <__main__.Person object at 0x0000016F450C7390>
               在将对象转为字符串时执行
         注意:返回值必须为字符串类型
       子类可以覆盖该方法来完成 对打印内容的自定义
    案例:说明
    # 将对象转换为字符串时执行
    #在打印前都会现将要打印的内容转为字符串  通过调用__str__函数
     
    ''''
    class Person:
    def __init__(self,name,age):
    self.name = name
    self.age = age
    # 将对象转换为字符串时执行
    def __str__(self):
    print("str run")
    return "my name is %s , age is %s" % (self.name,self.age)


    p = Person("rose",20)
    # print(p) #在打印前都会现将要打印的内容转为字符串 通过调用__str__函数

    str(p)
    '''
    """
    3.2__del__----------当对象被删除前会自动调用 该方法
          3.2.1什么时候会删除对象?
                1.程序运行结束 解释器退出 将自动删除所有数据
                2.手动调用del 时也会删除对象
                注意:该函数不是用来删除对象的
    3.2.2使用场景
               当你的对象在创建时,开启了不属于解释器的资源 例如打开了一个文件
               必须保证当对象被删除时 同时关闭额外的资源  如文件
     
    3.3也称之为析构函数  构造 的反义词
        构造 指的是从无到有
        析构 值从有到无
        简单的说就对象所有数据全部删除

    总结:__del__该函数 用于 在对象删除前做一些清理操作
     
    案例说明:

    """
    # 假设要求每一个person对象都要绑定一个文件
    class Person:
        def __init__(self,name,path,mode="rt",encoding="utf-8"):
            self.name = name
            self.file = open(path,mode,encoding=encoding)
     
        # 读取数据的方法
        def read_data(self):
            return self.file.read()

        def __del__(self):
            print("del run!")
            self.file.close()
    ```
     
    4.#  反射 -------英文中叫反省 (自省)  
        4.1面向对象中的反省
                                     指的是,一个对象必须具备,发现自身属性,以及修改自身属性的能力;  
    一个对象在设计初期,可能考虑不够周全后期需要删除或修改已经存在的属性, 和增加属性
     
    ## 反射就是通过字符串来操作对象属性
     
     
         4.2涉及到的方法:
    ```
    hasattr 判断是否存在某个属性
    getattr 获取某个属性的值
    setattr 新增或修改某个属性
    delattr 删除某个属性
    ```
    案例:说明
    ```
    class MY_CMD:
        def dir(self):
            os.system("dir")
        def ipconfig(self):
            os.system("ipconfig")
    cmd = MY_CMD()
    while True:
        name = input("请输入要执行的功能:")
        if hasattr(cmd,name):
            method = getattr(cmd,name)
            print(method)
            method()
        else:
            print("sorry this method is not exists....!")
    ```
     
    5# 动态导入模块------前置技能
    ```
    """
    直接写import 称之为静态导入  建立在一个基础上:提前已经知道有这个模块
    动态导入  指的是  在需要的任何时候 通过指定字符串类型的包名称来导入需要的模块

    import importlib
    mk = importlib.import_module(m_name)
    mk 即导入成功的模块
    """

    该方式常用在框架中 因为框架设计者不可能提前预知后续需要的模块和类
    ```
     
    总结:
     
    1封装:
    什么是封装  `*****`
    封装的好处  `*****`
    如何封装
    封装的原理
    property    `*****`
    ​ setter  deleter  
    计算属性
    2.多态: 
    ​ 多态指的是 多个不同类型对象可以响应同一个方法产生不同的结果   `*****`
    ​ 好处 `*****`
     好处:     只需要学习基类中的使用方法即可, 不需要关心具体的哪一个类 以及实现的   以不变应万变   提高了灵活性
     提高扩展性
     
     如果没有多态  需要分别学习 person  cat pig 的不同使用方法 这对于使用者而言太麻烦了
    ​ 如何实现多态  鸭子类型 
     
     
    3.# 常用的内置函数
     
                             1. `__str__`
     
                             2.  `__del__`
    4.#  反射 -------英文中叫反省 (自省)  
        面向对象中的反省
     
    5.# 动态导入模块------前置技能 
     
     
     
  • 相关阅读:
    【bzoj2733】永无乡(无旋treap启发式合并 + 并查集)
    【bzoj2002】弹飞绵羊(分块)
    【bzoj2724】蒲公英(分块)
    【最大M子段和】dp + 滚动数组
    【最大连续子段和】单调队列 + 前缀和优化
    【广告印刷】单调队列
    【烽火传递】dp + 单调队列优化
    【志愿者选拔】单调队列、输入优化
    【Sliding Window】单调队列
    【序列操作V】平衡树(无旋treap)
  • 原文地址:https://www.cnblogs.com/llx--20190411/p/10895846.html
Copyright © 2011-2022 走看看