zoukankan      html  css  js  c++  java
  • 类的封装,多态,内置函数

    1.多态

    2.封装:

      1.封装属性

      2.封装方法

      3.封装的原理

      4.封装存在的问题

      5.计算属性

    3.类中内置函数

    1.多态

    多态是一种概念,指的是某种事物具备多个不同形态

    例如 水:气态,固态,液态

        动物:猫,狗,猪

    OOP 中,标准解释:多个不同类型对象 可以响应同一个方法 并且产生不同结果

    多态的好处:

      只需要学习基类中的使用方法即可,不需要关心具体的哪一类,以及实现的,以不变应万变,提高了扩展性

    案例:

    2.封装

    什么是封装:

      对外部隐藏内部的属性,以及实现细节,给外部提供使用的接口

    注意:

      封装有隐藏的意思,但不是单纯的隐藏

    学习封装的目的:

      就是为了能够限制外界对内部数据的访问

    python中属性的权限分为两种:

      1.公开的:没有任何限制,谁都可以访问

      2.私有的:只有当前类本身能够访问

    默认为公共的

    如何封装:

      在类内定义的属性前加 __ 开头的方法

    为什么要封装:

      1.提高安全性: 封装属性

      2.隔离复杂度: 封装方法

    一个类中分为两种数据:-->属性和方法

    封装的原理:

      python 是通过 <变形> 的方式来是实现封装的

      如何变形: 在名称带有双下划线开头的变量名字前添加_类名, 如:_Person_id_card

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

    封装属性

      封装属性

      当这个对象存在一个机密性的属性,例如人的身份证,银行卡密码等等,这样的属性不应该被外界直接访问。可以封装起来

    案例:

    # 封装属性
    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)
    
    
    # 对私有属性的访问以及修改
    
    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('余额为1000000000,请输入取款金额')
    
        def __save_record(self):
            print('记录流水。。。。。。')
    
    
    atm = ATM()
    
    # 以下功能无法单独调用
    # atm.user_auth()
    # atm.input_money()
    # atm.save_record()
    
    # 必须通过此接口来调用
    atm.withdraw()

    Property

    Property作用:

        将一个方法伪装成普通属性

    为什么用property :

         希望将访问私有属性和普通属性的方式变得一致

    与property相关的两个装饰器

    setter 

      用点语法给属性赋值时出发

    deleter

      用点语法删除属性时出发

    案例:

    # Property装饰器
    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):
            del self.__dict__['_Teacher__salary']
    
    '''
        通常,property 用于操作私有属性
    被封装的属性在访问时,需要调用方法,而普通属性直接点就OK,这样一来对于对象的使用者而言
    就必须知道要访问的属性,是私有的还是公开的,然后调用对应的方法,使用起来比较麻烦,而property装饰器的方法
    就是将访问私有属性和普通属性的方式变得一致
    '''
    t = Teacher('egon',38,100000)
    print(t.salary)     # 100000  直接调用
    
    t.salary = 500
    print(t.salary)     # 500  直接修改
    
    # 删除对象
    del t.name
    print(t.__dict__)   # {'age': 38, '_Teacher__salary': 500}  没有name属性了

    计算属性:

    什么是计算属性,一个属性它的值不是固定死的,而是通过动态产生的

    '''
    property 的另一种使用场景,计算属性
    什么是计算属性  一个属性,它的值不是固定死的,而是通过计算动态产生的
    比如下面案例BMI
    '''
    
    
    class Person:
        def __init__(self, name, height, weight):
            self.name = name
            self.height = height
            self.weight = weight
            # BMI公式 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.8,70)
    # print(p.BMI)
    
    p.weight = 65
    print(p.BMI)
    
    # 被封装的内容(私有的)   不可以被继承

     

    3.类中内置函数

     __str__

    '''
    类中的__str__
        该方法在object中有定义,默认行为 返回对象类型以及地址<__main__.Person object at 0x0000016F450C7390>
        在将对象转为字符串时执行
        注意: 返回值必须为字符串类型
        子类可以覆盖该方法来完成,对打印内容的自定义
    '''
    
    
    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)

    __del__

    '''
    __del__
    当对象被删除前会自动调用该方法
    什么时候会删除对象?
        1.程序运行结束,解释去退出,将自动删除所有数据
        2.手动调用del 时也会删除对象
    注意:该函数不是用来删除对象的
    
    使用场景
        当你的对象在创建时,开启了不属于解释器的资源,例如打开了一个文件
        必须保证当对象被删除时,同时关闭额外的资源,比如文件
        
    也称之为析构函数,  构造的反义词
        构造:从无到有
        析构:从有到无
        简单的说,就是把所有对象所有数据全部删除
        
    总结:__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()
    
        # 在程序结束时,会执行del,把文件清理关闭。
        def __del__(self):
            print('del run')
            self.file.close()
    
    
    p = Person('rose', '本周内容')
    print(p.read_data())

    反射:

    # 英文中叫反省(自省)
    
    # 面向对象中的反省指的是,一个对象必须具备,发现自身属性,以及修改自身属性的能力
    # 一个对象在设计初期,可能考虑不够周全后期需要删除或修改已存在的属性,和增加属性
    
    # 反射就是通过字符串来操作对象属性
    
    # 涉及到的方法:
    # hasattr() 判断是否存在某个属性
    # getattr() 获取某个属性
    # setattr() 新增或修改某个属性
    # delattr() 删除某个属性
    
    import os
    
    
    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 称之为静态导入,建立在一个基础上:提前已经知道有这个模块

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

    '''
    直接写import  称之为静态导入 ,建立在一个基础时,提前已经知道有这个模块
    动态导入:指的时 在需要的任何时候 通过指定字符串类型包名称来导入需要的模块
    import importlib
    mk 即导入成功的模块
    '''
    import importlib
    
    m_name = input('请输入要导入的模块名称:')
    
    mk = importlib.import_module(m_name)
    print(mk)
    
    from build_house import conf
    print(conf)

     

  • 相关阅读:
    数据库自动重连
    golang slice分割和append copy还是引用
    Unicode和UTF-8的关系
    golang的内置类型map的一些事
    svn sync主从同步学习
    CMake学习笔记
    常用排序总结
    优先队列实现Huffman编码
    linux 下C++查询mysql数据库
    ubuntu下C++连接mysql数据库
  • 原文地址:https://www.cnblogs.com/liguodeboke/p/10894148.html
Copyright © 2011-2022 走看看