• 多态,抽象类,鸭子类型,classmethod和staticmethod,isinstance与issubclass和反射


    多态

    多态指的是同一种类型的事物,不同的形态

    多态的目的:

    多态也称之为多态性,目的是为了在不知道对象具体类型的情况下,统一对象调用方法的规范(例如名字)

    多态的表现形式之一就是继承:

    先抽象,再继承

    父类:定制一套统一的规范 如方法名统一

    子类:遵循父类的统一的规范 如子类遵循父类方法名的统一

    ps:在python中不会强制限制 子类必须要遵循 父类的规范,所以出现了抽象类

    class Father:
        def func1(self):
            pass
        def speak(self);
        	pass
    class Sub1(Father):
        def func1(self):
            pass
        def speak(self):
            pass
    class Sub2(Father):
        def func1(self):
            pass
        def speak(self):
            pass
    

    抽象类

    什么是抽象类:

    在python内置的abc模块中,有一个抽象类

    抽象类的作用:

    让子类必须遵守父类的编写规范

    如何实现抽象类:

    -父类需要继承abc模块中,metaclass = adb.ABCMeta

    -在父类的方法中,需要装饰上 abc.abstractmethod

    注意:在python中不推荐使用抽象类

    注意: 子类必须按照父类的方法编写规范,缺一不可。父类中有几个抽象方法,子类就必须要定义几个

    import abc
    错误示范
    
    # 父类
    class Father(metaclass=abc.ABCMeta):
    
        # 方法吃
        @abc.abstractmethod
        def eat(self):
            pass
    
        # 方法叫
        @abc.abstractmethod
        def speak(self):
            pass
    
    
    class Sub(Father):
        def eat(self):
            pass
    
        def drink(self):
            print(1)
    
    
    sub_obj = Sub()
    sub_obj.eat()
    执行就会报错
    父类中有几个抽象方法,子类就必须要定义几个
    
    正确示范
    # 父类
    class Father(metaclass=abc.ABCMeta):
    
        # 方法吃
        @abc.abstractmethod
        def eat(self):
            pass
    
        # 方法叫
        @abc.abstractmethod
        def speak(self):
            pass
    
    
    class Sub(Father):
        def eat(self):
            pass
    
        def speak(self):
            print(1)
    	
        def drink(self):
            pass
    
    

    鸭子类型

    什么是鸭子类型:

    不同的对象,只要长的像鸭子,动作行为像鸭子,那它就是鸭子

    ​ 鸭子类型是多态的一种表现形式

    为什么要有鸭子类型:

    不同的对象,先抽象出相同的类型的方法,给他们定制一套统一的规范

    所有的类,在定义时都按照统一的规范进行编写

    多态的三种表现形式:

    继承父类:

    ​ 耦合度高,程序的可扩展性低

    继承抽象类:

    ​ 耦合度极高,程序的可扩展性极低

    鸭子类型:

    ​ 耦合度低,程序的可扩展性高

    注意:在python中强列推荐使用鸭子类型

    classmethod与staticmethd

    classmethod与staticmethod都是python解释器内置的装饰器

    classmethod:

    是一个装饰器,给在类内部定义方法中修饰,将类内部的方法变为“类的绑定方法”

    staticmethod:

    静态方法

    是一个装饰器,给在类内部定义方法中修饰,将类内部的方法变为非绑定方法

    回顾:

    对象的绑定方法:

    由对象来调用,由谁来调用,会将谁作为第一个参数传入。

    类的绑定方法:

    由类来调用,由谁来调用,会将谁当作第一个参数传入

    非绑定方法:

    可以由对象或类来调用,谁来调用都是一个普通方法(普通函数),方法需要传入几个参数,就得传入几个

    注意:__ class __: 是用来查看当前对象的类

    import uuid 用来产生随机字符串的模块,由时间戳以及某种算法结合而成,会产生一串世界上独一无二的字符串

    print(uuid.uuid4())

    classmethod_Demo:
    class DB:
        __data = 'nothing can not be done!'
    
        def __init__(self, user, pwd, role):
            self.user = user
            self.pwd = pwd
            self.role = role
    
        # cls指的是类
        @classmethod
        def check_db(cls, user, pwd, role):
            obj = cls(user, pwd, role)
            if obj.user == 'tank' and obj.pwd == '123' and obj.role =='admin':
                print('通过检验!')
                print(obj.__data)
    
    
    DB.check_db('tank', '123', 'admin')
    
    
    user_info = {
        'user': None
    }
    
    
    class User:
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
            self.__uid = uuid.uuid4()
    
        def register(self, user, pwd):
            self.user = user
            self.pwd = pwd
    
            with open('user.txt', 'w', encoding='utf-8') as f:
                f.write(
                    f'{self.name},{self.age},{self.sex},{self.user},{self.pwd}'
                )
    
        def login(self, user, pwd):
            if self.user == user and self.pwd == pwd:
                print('通过登录!')
                user_info['user'] = user
            else:
                print('用户名或密码错误!')
    
    
    user_obj = User('tank', 17, 'male')
    user_obj.register('tank_jam', '123')
    user_obj.login('tank_jam', '123')
    
    
    通过登录!
    

    isinstance与issubclass是python的内置模块

    ​ -isinstance:判断一个对象是否是另一个类的实例

    ​ -issubclass:判断一个类是否是类一个类的子类

    ​ 如果是:True

    ​ 如果不是:False

    # isinstance:
    class Foo:
        pass
    
    class Boo:
        pass
    
    foo_obj = Foo()
    boo_obj = Boo()
    
    print(isinstance(foo_obj, Foo))  # True
    print(isinstance(boo_obj, Foo))  # False
    
    
    # issubclass
    class Father:
        pass
    
    
    class Sub(Father):
        pass
    
    
    class Foo:
        pass
    
    
    print(issubclass(Sub, Father))  # True
    print(issubclass(Foo, Father))  # False
    

    反射:

    ​ 反射指的是通过“字符串”对对象的属性进行操作

    ​ -hasattr: 通过“字符串”判断对象的属性或方法是否存在 hasattr(self, str)

    ​ -getattr: 通过“字符串”获取对象的属性或方法 getattr(self, str, 默认值)

    ​ -setattr:通过“字符串”设置对象的属性或方法 seet(self, str, 属性值)

    ​ -delattr:通过“字符串”删除对象的属性或方法 delattr(self, str)

    注意:反射的四个方法都是python内置的

    class Foo:
        def __init__(self, x, y):
            self.x = x
            self.y = y
    
    
    foo_obj = Foo(10, 20)
    print(hasattr(foo_obj, 'x'))
    print(hasattr(foo_obj, 'z'))
    
    print('=========================')
    
    print(getattr(foo_obj, 'x'))
    print(getattr(foo_obj, 'z'))
    
    结果:
    True
    False
    =========================
    10
    Traceback (most recent call last):
      File "F:/python_work/python_oldboyedu_learn/day23/反射.py", line 14, in <module>
        print(getattr(foo_obj, 'z'))
    AttributeError: 'Foo' object has no attribute 'z'
        
        
    setattr(foo_obj, 'z', 100)
    print(hasattr(foo_obj, 'z'))
    
    print('===================')
    
    delattr(foo_obj, 'z')
    print(hasattr(foo_obj, 'z'))
    
    
    结果:
    True
    ===================
    False
    
    

    反射应用:

    class FileControl:
    
        def run(self):
            while True:
                # 让用户输入上传或下载命令
                user_input = input('请输入 上传 upload 或 下载 download:').strip()
    
                # 通过用户输入的字符串判断方法是否存在,然后调用相应的方法
                if hasattr(self, user_input):
                    func = getattr(self, user_input)
                    func()
                    break
                else:
                    print('输入有误!')
    
        def upload(self):
            print('文件正在上传。。。')
    
        def download(self):
            print('文件正在下载中。。。')
    
    
    file_control_obj = FileControl()
    file_control_obj.run()
    
    
    结果:
    请输入 上传 upload 或 下载 download:as
    输入有误!
    请输入 上传 upload 或 下载 download:upload
    文件正在上传。。。
    
    
    
  • 相关阅读:
    DataGrid
    取整、取小数点位数
    如何跨浏览器使用连续字符的换行
    如何给 legend 标签设定宽度
    25个简洁优美的网站设计
    重新发现HTML表格
    用户研究角度看设计(2):用户为何视若无睹
    lineheight 属性的继承问题
    jQuery技巧总结
    web2.0网站配色方案
  • 原文地址:https://www.cnblogs.com/godlover/p/11950725.html
Copyright © 2020-2023  润新知