• 封装 多态 常用内置函数 反射 动态导入模块


    封装

    什么是封装 *****

    封装的好处 *****

    property *****

    什么是封装:对外部隐藏内部的属性,以及实现细节,给外部提供使用的接口
             *封装有隐藏的 意思,但不是单纯的隐藏
    封装的目的:限制外部对内部数据的访问

    py中 属性的权限分为两种:  1.公开的:  没有任何限制,谁都能访问
                                                  2.私有的:只有当前类本身能够访问

             *默认为公开的

    为什么要封装:1.提高安全性  =====>封装属性:当这个对象存在一个机密性的属性。eg:  身份证 不应被外界直接访问,那就封装起来

              2.隔离复杂度=====>封装方法:一个为内部提供支持的方法,不应被外界直接访问,那就封装起来

     

     

    封装属性:
    
    ```python
    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)
    ```
    
    对私有属性的访问以及修改
    
    ```python
    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!")
    ```
    什么样的方法应该被封装起来 :一个为内部提供支持的方法,不应该让外界直接访问,就封装起来

     

    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("记录流水....")

    封装的原理: py中是通过变形的方式来实现的

    如何变形:在名称带有双下划线的变量名字前添加_类名    eg _Person__id_card

            通过变形后的名字可以直接访问被隐藏的属性, 但不建议这么做。变形仅在类的定义阶段发生一次,后续再添加的带有双下划线的任何属性都不会变形,  就是普通属性

    封装存在的问题:

    property的作用 : 将一个方法伪装成普通属性

    why用property:是希望将访问私有属性和普通属性的方式变得一致

    setter: 用点语法 给属性赋值时触发

    deleter:用点语法删除属性时触发

     

    eg:
    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"]

    property的另一种使用场景       

    计算属性:一个值它的属性不是固定死的,而是通过计算动态产生的   eg: 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

    多态

    多态:不是一个具体的技术或代码,而是指多个不同类型对象  可以相应同一个方法,产生不同的结果

    生活中可以理解为:某种事物具备多个不同形态   eg:水: 水的  固液气 三态

    多态带来的好处:只要学习积累中的方法就行,不需要关心具体的哪一类实现的,  提高灵活性与扩展性

    如何实现多态:鸭子类型

    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()

    鸭子类型就是典型的多态,多种不同类型 ,使用方法一样

    常用的内置函数

    __del__:当对象被删除前会自动调用该方法

    什么时候会删除对象:i:程序运行结束,解释器退出 将自动删除所有数据,
              o:手动调用del   时也会删除对象

    * *该函数不是用来删除对象的

    使用场景:当你的对象在创建时,开启了不属于解释器的资源,  eg: 打开一个文件
                     必须保证对象被铲除时 同时关闭额外的资源      eg:文件

    它也被称之为析构函数   构造的  反义词 ,      构造:是指从无到有           析 构:从有到无,简单地说就是对象的所有数据全部删除

    __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()


    __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)

    反射(反省,自省)就是通过字符串来操作对象属性

    反省:是指一个对象必须具备发现自身属性,以及修改自身属性的能力。

    一个对象在设计初期,可能考虑不周全后期需要删除或修改已经存在的属性,和增加属性

    涉及到的方法: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....!")

    动态导入模块

    静态导入:直接写import的douru 导入方式        前提:提前知道有这个模块

    动态导入:在需要的任何时候    通过指定字符串类型的包名称来导入需要的模块

    eg:

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

    where:  常用在框架中,   因为框架设计者不可能提前知道后续需要的模块何类

          

  • 相关阅读:
    最简单跨平台的日志库
    linux文件锁
    Linux 获取屏幕分辨率与窗口行列数(c/c++)
    linux 信号机制
    记一次函数异常(getopt_long)
    程序单实例运行
    简单地 Makefile 书写
    学习go的一些笔记
    20200930 10. Netty 核心源码剖析
    20200930 9. TCP 粘包和拆包 及解决方案
  • 原文地址:https://www.cnblogs.com/wyf20190411-/p/10896106.html
Copyright © 2020-2023  润新知