• 面向对象—多态,反射


    一、多态

    1.什么是多态?

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

    2.多态的目的:

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

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

    ​ -先抽象,再继承

    ​ 父类:定制一套统一的规范(比如:方法名统一)

    ​ 子类:遵循父类的统一的规范(比如:子类遵循父类方法名的统一)

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

    3.多态的三种表现形式:

    ​ -继承父类

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

    ​ -继承抽象类

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

    ​ -鸭子类型

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

    ​ 缺点:造成了代码的冗余

    ​ 注意:在python中,强烈推荐使用鸭子类型

    #子类遵循父类统一的规范,比如方法名一致
    #动物类
    class Animal:
        def eat(self):
            pass
        def speak(self):
            pass
    
    #猪类
    class Pig(Animal):
        def eat(self):   #方法名与父类一致
            print('bia 唧。。。。')
        def speak(self):  #方法名与父类一致
            print('哼哼哼。。。')
    
    
    #猫类
    class Cat(Animal):
        def eat(self):
            print('咬ji 咬ji。。。')
    
        def speak(self):
            print('喵喵喵。。。')
    
    #狗类
    class Dog(Animal):
        def eat(self):
            print('舔ji 舔ji 。。。')
        def speak(self):
            print('汪汪汪。。。')
    
    animal1 = Dog()
    animal2 = Cat()
    animal3 = Pig()
    #让动物们叫起来
    animal1.speak() #汪汪汪。。。
    animal2.speak() #喵喵喵。。。
    animal3.speak() #哼哼哼。。
    

    多态使用

    #猪类
    class Pig:
        def eat(self):
            print('bia 唧。。。')
        def speak(self):
            print('哼哼哼。。。')
    #猫类
    class Cat:
        def eat(self):
            print('咬ji ,咬ji。。。')
    
        def speak(self):
            print('喵喵喵。。。')
    
    #狗类
    class Dog:
        def eat(self):
            print('舔ji  舔ji。。。')
        def speak(self):
            print('汪汪汪。。。')
    
    dog = Dog()
    pig = Pig()
    cat = Cat()
    # dog.speak()
    # pig.speak()
    # cat.speak()
    #多态之炫技
    def SPEAK(animal):
        animal.speak()
    SPEAK(dog)
    SPEAK(pig)
    SPEAK(cat)
    
    str1 = 'tank is very handsome!!!'       #字符串也是类
    list1 = ['tank','is', 'very', 'handsome!!'] #列表也是类
    print(str1.__len__())
    print(list1.__len__())
    #自定义统计长度函数
    def LEN(obj):
        return obj.__len__()
    
    print(LEN(str1))
    print(LEN(list1))
    

    二、抽象类

    1、什么是抽象类?

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

    2、抽象的作用:

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

    3、如何实现抽象类

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

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

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

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

    import abc
    #父类
    class Animal(metaclass=abc.ABCMeta):    #变成抽象类
        @abc.abstractmethod
        #方法吃
        def eat(self):  #添加装饰器,变成抽象类方法
            pass
        #方法叫
        @abc.abstractmethod
        def speak(self):    #添加装饰器。变成抽象类方法
            pass
    
    #猪类
    class Pig(Animal):
        def run(self):
            pass
        def eat(self):  #与父类方法名必须一致,
            print('bia 唧。。。')
        def speak(self): #与父类方法名一致
            print('哼哼哼。。。')
    print(Pig.__dict__) #打印Pig类名称空间
    print(Animal.__dict__) #打印Animal父类的名称空间
    pig_obj = Pig()
    

    三、鸭子类型

    1.什么是鸭子类型?

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

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

    2.为什么要有鸭子类型?

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

    ​ 所有的类,在定义时都按照统一的规范进行定义类的方法

    #猪类
    class Pig:
        def eat(self):
            print('bia 唧。。。')
        def speak(self):
            print('哼哼哼。。。')
    
    #猫类
    class Cat:
        def eat(self):
            print('咬ji 咬ji。。。')
        def speak(self):
            print('喵喵喵。。。')
    
    #狗类
    class Dog:
        def eat(self):
            print('舔ji 舔ji。。。')
        def speak(self):
            print('汪汪汪。。。')
    '''
    这三个类的方法,就称为鸭子类型
    '''
    

    四、classmethod 和 staticmethod

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

    classmethod:

    ​ 是一个装饰器,给在类内部定义的方法装饰,将类内部的方法变为‘’类的绑定方法‘’。

    staticmethod(也叫静态方法):

    ​ 是一个装饰器,给在类内部定义的方法装饰,将类内部的方法变为‘’非绑定方法‘’。

    -对象的绑定方法(在类内部定义一个方法即可):

    ​ -由对象来调用,由谁来调用,会将谁(对象)当做第一个参数传入该方法

    -类的绑定方法(在类内部方法中,使用classmethod装饰器):

    ​ -由类来调用,由谁来调用,会将谁(类)当做第一个参数传入该方法

    -非绑定方法(在类内部方法中,使用staticmethod装饰器):

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

    #classmethod_Demo:
    class DB:
        __data = 'tank is very hangsome'
        def __init__(self, user, pwd, role):
            self.user = user
            self.pwd = pwd
            self.role = role
        @classmethod        #将类内部的方法变为''类的绑定方法''
        def init(cls,user, pwd, role): #cls--->指的是类
            #在类方法内部调用产生一个实例---->对象
            return cls(user, pwd, role)
    
        #查看数据方法
        @classmethod
        def check_db(cls, user, pwd, role): #cls--->指的是类
            #在类方法内部调用类产生一个实例----》对象
            obj = cls(user, pwd, role)
            #1.查看数据前,必须要通过校验
            if obj.user=='tank' and obj.pwd == '123' and obj.role == 'admin':
                print('校验通过。。。')
                print(cls.__data)
                return cls.__data
    DB.check_db('tank','123','admin')     #类调用 tank is very hangsome
    db_obj = DB('tank','123','admin')
    
    # db_obj.check_db('tank','123','admin')
    # __class__:查看当前对象的类
    print(db_obj.__class__) #<class '__main__.DB'>
    #staticmethod_Demo:
    import uuid #用于产生随机字符串的模块
    '''
    uuid模块由时间戳及某种算法组合而成,会产生一串世界上独一无二字符串。
    print(uuid.uuid4())
    '''
    class Foo:
        @staticmethod
        def func(res):
            print(res)
    
    obj = Foo()
    #对象调用非绑定方法
    obj.func(123)  #123
    #类调用非绑定方法
    Foo.func(1234)  #1234
    

    五、isinstance与issubclass

    isinstance 与issubclass 是python的内置模块:

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

    ​ -如果是:返回True

    ​ -如果不是:返回False

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

    ​ -如果是:返回True

    ​ -如果不是:返回False

    #isinstance: 判断一个对象是否是另一个类的实例
    class Foo:
        pass
    class Boo:
        pass
    foo_obj = Foo()
    boo_obj = Boo()
    #print(isinstance(对象, 类))
    print(isinstance(foo_obj, Foo)) #True
    print(isinstance(boo_obj, Foo)) #False
    
    #issubclass #判断一个类是否是另一个类的子类
    class Father:
        pass
    
    class Sub(Father):
        pass
    class Foo:
        pass
    #print(issubclsss(子类, 父类)
    print(issubclass(Sub, Father))  #True
    print(issubclass(Foo,Father))   #False
    

    六、反射

    反射指的是通过‘’字符串‘’对对象、类的属性或方法进行操作

    -hasattr:通过‘’字符串‘’判断对象的属性或方法是否存在

    ​ 存在返回Ture,否则返回False

    ​ 例:hasattr(对象, ’对象的属性或方法名字符串‘)

    -getattr:通过‘’字符串‘’获取对象的属性或方法

    ​ 存在返回获取属性或方法,否则返回报错

    ​ 例:getattr(对象,’对象属性或方法名字符串‘, ’默认值‘)

    -setattr:通过‘’字符串‘’设置对象的属性或方法

    ​ setattr(对象,’对象的属性或方法名字符串‘,‘属性值 ’)

    -delattr:通过‘’字符串‘’删除对象的属性或方法

    ​ delattr(对象,’对象的属性或方法名字符串‘ )

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

    class Foo:
        def __init__(self,x, y):
            self.x = x
            self.y = y
        def tell_all(self, username1):
            self.usname1 = username1
            if username1 == 'han':
                print('from .....')
    
    foo_obj = Foo(10, 20,)
    print(foo_obj.tell_all('han'))      #打印from。。。返回None
    #hasattr:  通过'字符串'判断对象的属性或方法是否存在
    #通过字符串x 判断对象中是否存在x属性
    print(hasattr(foo_obj, 'x')) #True
    print(hasattr(foo_obj, 'y'))#True
    print(hasattr(foo_obj, 'z'))#False
    
    #getattr: 通过'字符串'获取对象属性或方法
    res = getattr(foo_obj, 'x')
    print(res)  #10
    #若属性不存在,则返回默认值
    res1 = getattr(foo_obj, 'z', '默认值') #这里的'默认值'是自定义的,类似于字典.get的用法
    print(res1) #默认值
    
    #setattr
    setattr(foo_obj, 'z', 30) # 为foo_obj 设置一个属性z,值为30
    print(hasattr(foo_obj, 'z')) #True
    
    #delattr
    delattr(foo_obj, 'x')
    print(hasattr(foo_obj, 'x')) #False
    
    print(getattr(foo_obj, 'username1', '默认值'))  #默认值,只能获取方法,不能获取方法内参数
    print(getattr(foo_obj, 'tell_all', '默认值')('han'))    #打印from。。。返回None
    print(hasattr(foo_obj, 'tell_all')) #True
    setattr(foo_obj, 'd',14)
    print(getattr(foo_obj, 'd')) #14
    print(foo_obj.__dict__)  #查看名称空间:{'y': 20, 'usname1': 'han', 'z': 30, 'd': 14}
    

    反射应用:

    class FileControl:
    def run(self):
        while True:
            # 让用户输入上传或下载功能的命令:
            user_input = input('请输入 上传(upload) 或 下载(download) 功能:').strip()
    
            # 通过用户输入的字符串判断方法是否存在,然后调用相应的方法
            if hasattr(self, user_input):
                func = getattr(self, user_input)
                func()
            else:
                print('输入有误!')
    
    def upload(self):
        print('文件正在上传...')
    
    def download(self):
        print('文件正在下载...')
        
    file_control_obj = FileControl()
    file_control_obj.run()
    
    
    
  • 相关阅读:
    网曝!互联网公司那些老司机才懂的秘密~~
    中国IT行业薪资:与销售相比,程序员真得很“穷”
    太简单了,教你去掉Java代码中烦人的“!=null”
    怎么判断自己在不在一家好公司?
    内部泄露版!互联网大厂的薪资和职级一览
    重磅!GitHub突然宣布,对全球人免费开放全部核心功能
    痛心!Pandownload开发者被抓!我终于决定使用Docker搭建一个多端同步网盘!
    退税:我承认我有赌的成分
    golang实现的简单优先队列
    ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (13)解答
  • 原文地址:https://www.cnblogs.com/xy-han/p/11983214.html
Copyright © 2020-2023  润新知