• day20(类 )


    多态

    # 当子类与父类都存在run() 函数时,子类run()覆盖了父类的run()方法,我们获得了继承的另一个好处也就是所谓的 多态
    # 多态:
    # 什么是多态 . 一种类型的多种对象
    # 例 有序数据类型 --> 多态 -->列表 字符串 元组
    ''''''
    class Animal:
        def cry(self):
            print('Animal')
    class Dog(Animal):
        def cry(self):
            print('Dog')
    dog = Dog()
    animal = Animal()
    print(isinstance(dog,Dog))
    print(isinstance(dog,Animal))
    print(isinstance(animal,Dog))
    print(isinstance(animal,Animal))
    # ps 子类的对象其数据类型也可以是其父类
    
    """多态还常用来规范数据类型 ==> 类似于静态语言中的接口,但是没有强制性 """
    """在动态类型叫做鸭子类型 ==> """
    
    """ 当我们需要传入Dog、Cat、Tortoise……时,我们只需要接收Animal类型就可以了,
     因为Dog、Cat、Tortoise……都是Animal类型,然后,按照Animal类型进行操作即可。
     由于Animal类型有run()方法,因此,传入的任意类型,只要是Animal类或者子类,
     就会自动调用实际类型的run()方法,这就是多态的意思:"""
    '''对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用run()方法。
    对于Python这样的动态语言来说,则不一定需要传入Animal类型。我们只需要保证传入的对象有一个run()方法就可以了'''

    封装

    # 类(class) 其实已经算是一种封装 --> 将逻辑和算法部分数据封装起来
    # 深度封装 变量名前面加  __ 对变量进行封装 只能在类内部调用 .不是真正的封装而是将变量名变形
    #
    # __run() --> _foo__run() : __name --> _foo__name
    """ 变形在定义的时候发生"""
    
    
    # 封装的用处
    # 1 隔离复杂度
    class ATM:
        def __card(self):
            print('插卡')
    
        def __auth(self):
            print('用户认证')
    
        def __input(self):
            print('输入取款金额')
    
        def __print_bill(self):
            print('打印账单')
    
        def __take_money(self):
            print('取款')
    
        def withdraw(self):
            self.__card()
            self.__auth()
            self.__input()
            self.__print_bill()
            self.__take_money()
    
    
    # 2 添加数据的限制
    class Teacher:
        def __init__(self, name, age):
            # self.__name=name
            # self.__age=age
            self.set_info(name, age)
    
        def tell_info(self):
            print('姓名:%s,年龄:%s' % (self.__name, self.__age))
    
        def set_info(self, name, age):
            if not isinstance(name, str):
                raise TypeError('姓名必须是字符串类型')
            if not isinstance(age, int):
                raise TypeError('年龄必须是整型')
            self.__name = name
            self.__age = age
    
    
    property
    ''' @property
        @*.setter
        @*.deleter
        将函数封装为数据'''
    
    
    class School:
        def __init__(self):
            pass
    
        @property
        def select(self):
            return 'select'
    
        @select.setter
        def select(self):
            return 'select'
    
        @select.deleter
        def select(self):
            return 'select'
    
    
    s1 = School()
    print(s1.select)
    # 将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,
    # 这种特性的使用方式遵循了统一访问的原则
    
    class Foo:
        def __init__(self, val):
            self.__NAME = val  # 将属性隐藏起来
    
        @property
        def name(self):
            return self.__NAME
    
        @name.setter
        def name(self, value):
            if not isinstance(value, str):  # 在设定值之前进行类型检查
                raise TypeError('%s must be str' % value)
            self.__NAME = value  # 通过类型检查后,将值value存放到真实的位置self.__NAME
    
    
        @name.deleter
        def name(self):
            raise PermissionError('Can not delete')
    
    
    f = Foo('lili')
    f.name
    f.name = 'LiLi'  # 触发name.setter装饰器对应的函数name(f,’Egon')
    # f.name = 123  # 触发name.setter对应的的函数name(f,123),抛出异常TypeError
    # del f.name  # 触发name.deleter对应的函数name(f),抛出异常PermissionError

    类的内置函数

    # 反射
    '''
    getattr()
    setattr()
    hasattr()
    delattr()
    '''
    # 输入的字符串对对象进行操作
    # 设 输入字符串为'name'
    # hasattr(obj,'name) 检测obj中是否存在name属性
    # getattr(obj,'name) 得到obj中name属性 一般与hasattr连用
    # setattr(obj,'name) 建立obj中的name属性
    """练习"""
    
    
    class Student:
        def __init__(self):
            cmd = input('cmd')
            if hasattr(self, cmd):
                func = getattr(self, cmd)
                func()
        def name(self):
            print('name')
    
    
    stu = Student()
    cmd = input('cmd')
    if hasattr(stu, cmd):
        func = getattr(stu, cmd)
        func()
    setattr(stu, 'age', 18)
    
    # 内置方法
    # __str__
    # print()
    
    # __del__
    # 回收用于回收系统资源
    
    # __ep__  ==
    #
    # __add__  +

    类的数据获取

    # isinstance(obj,Class)
    # 判断obj是否是 Class 的子类
    dir()
    # 获取对象的所有属性和方法
    class Cla:
    def foo(self):
    pass
    class Gra(Cla):
    def bar(self):
    pass
    print(Gra.__dict__)
    a = Gra()
    print(dir(Cla))
    print(dir(a))
    #
    .

    绑定方法未绑定方法

    
    
    """绑定方法"""
    '''类一'''
    # 默认绑定给对象
    # self
    '''类二'''
    classmethod
    # 调用classmethod 将方法绑定给类
    class Foo:
    @classmethod
    def func(cls):
    print('func_1')
    Foo.func()

    '''未绑定方法'''

    staticmethod
    # 调用staticmethod 使函数不绑定 类与对象都可以调用


    class Foo:
    @classmethod
    def func(cls):
    print('func_1')
    @staticmethod
    def f2():
    print('f2')
    bar = Foo()
    Foo.f2()
    bar.f2()





  • 相关阅读:
    springboot: 使web项目支持jsp
    springboot: 集成freemark模板引擎
    Springboot的优点和实现
    Spring的两种动态代理:Jdk和Cglib 的区别和实现
    JAVA单例模式:懒汉式,饿汉式
    java的内存管理 对象的分配与释放
    JAVA反射调用方法
    JAVA内置注解 基本注解
    图——图的定义与操作
    树——二叉树的线索化
  • 原文地址:https://www.cnblogs.com/lee1225/p/12663681.html
Copyright © 2020-2023  润新知