• python基础语法17 面向对象4 多态,抽象类,鸭子类型,绑定方法classmethod与staticmethod,isinstance与issubclass,反射**


    多态

    1.什么是多态?
    多态指的是同一种类型的事物,不同的形态。

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

      多态的表现 “形式之一” 就是继承:
        - 先抽象,再继承

        父类: 定制一套统一的规范。(比如: 方法名统一)
        子类: 遵循父类的统一的规范。(比如: 子类遵循父类方法名的统一)

      注意: 在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 = Pig()
    animal3 = Cat()
    
    # 让动物们叫起来
    animal1.speak()
    animal2.speak()
    animal3.speak()

    抽象类

    1.什么是抽象类?
      在python内置的abc模块中,有一个抽象类。

    2.抽象类的作用:
      让子类必须遵循父类的编写规范。

    3.如何实现抽象类
      - 父类需要继承abc模块中,metaclass=abc.ABCMeta
      - 在父类的方法中,需要装饰上 abc.abstractmethod


    注意: 在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__)
    print(Animal.__dict__)
    pig_obj = Pig()

    鸭子类型

    1.什么是鸭子类型?
      不同的对象,只要长得像鸭子,动作行为像鸭子,那它就是鸭子!

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

    2.为什么要有鸭子类型?
      不同对象,先抽象出相同类型的方法,给他们定制一套统一的规范
      所有的类,在定义时都按照统一的规范进行编写。

      - 多态的三种表现形式:
        - 继承父类 ****
          - 耦合度高,程序的可扩展性低

        - 继承抽象类 ***
          - 耦合度极高,程序的可扩展性极低

        - 鸭子类型: *****
          - 耦合度低,程序的可扩展性高

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

    # 猪类
    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("汪汪汪...")

    多态之炫技

    # 猪类
    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()
    
    # 多态之炫技
    def SPEAK(animal):
        animal.speak()
    
    SPEAK(dog)
    SPEAK(cat)
    SPEAK(pig)
    
    str1 = 'tank is very handsome!!!'
    list1 = ['tank', 'is', 'very', 'handsome!!!']
    
    # 自定义统计长度函数
    def LEN(obj):
        return obj.__len__()
    
    print(LEN(str1))    # 24
    print(LEN(list1))   # 4

    classmethod 与 staticmethod

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

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

    staticmethod:
      翻译: 静态方法
      是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “非绑定方法”。

    - 对象的绑定方法:
      - 由对象来调用,由谁来调用,会将谁(对象)当做第一个参数传入。

    - 类的绑定方法:
      - 由类来调用,由谁来调用,会将谁(类)当做第一个参数传入。

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

    # classmethod_Demo:
    class DB:
        __data = 'tank is very handsome!!!'
        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')
    obj=DB('tank','123','admin')
    obj.check_db('tank','123','admin') # 也可以,第一个传入参数依然是类,但没什么意义
    # staticmethod_Demo:
    class Foo:
        @staticmethod
        def func(res):
            print(res)
    obj = Foo()
    #对象调用非绑定方法
    obj.func(123)
    #类调用非绑定方法
    Foo.func(1234)

    uuid  用于产生随机字符串的模块

    import uuid  # 用于产生随机字符串的模块
    
    # 由时间戳以及某种算法组合而成,会产生一串世界上独一无二字符串。
    print(uuid.uuid4()) # f93f9c3b-eef4-4001-922e-2124b48ca7ab

    内置模块: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(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: 通过 字符串 判断对象的属性或方法是否存在,存在返回True, 否则返回False。

        hasattr(对象, '对象的属性或方法字符串')

      - getattr: 通过 字符串 获取对象的属性或方法是否存在,存在返回获取属性或方法, 否则返回报错。

        getattr(对象, '对象的属性或方法字符串', '默认值')

      - setattr: 通过 字符串 设置(添加/修改)对象的属性或方法。

        setattr(对象, '对象的属性或方法字符串', '属性的值')

      - delattr: 通过 字符串 删除 对象的属性或方法,若属性不存在,则报错。    

        delattr(对象, '对象的属性或方法字符串')

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

    class Foo:
        def __init__(self, x, y):
            self.x = x
            self.y = y
    
    foo_obj = Foo(10, 20)
    # 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
    
    # 若属性不存在,则返回默认值
    res = getattr(foo_obj, 'z', '默认值')
    print(res)  # 默认值
    
    # setattr
    setattr(foo_obj,'x',40)
    print(getattr(foo_obj,'x')) # 40
    # 为foo_obj设置一个属性z,值为30
    setattr(foo_obj, 'z', 30)
    print(hasattr(foo_obj, 'z'))  # True
    
    # delattr
    delattr(foo_obj, 'x')
    print(hasattr(foo_obj, 'x'))  # 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()
                else:
                    print('输入有误!')
    
        def upload(self):
            print('文件正在上传...')
    
        def download(self):
            print('文件正在下载...')
    
    
    file_control_obj = FileControl()
    file_control_obj.run()

     以下为验证,反射中将输入输入字符创转化为方法

    # 代码同上,用来测试反射里面类型变化
    class choose:    
        def run(self):
            while True:
                cmd = input('请输入命令:').strip()
                if hasattr(self,cmd):
                    print(getattr(self,cmd))    # 把字符串转化为方法
                    # <bound method choose.load of <__main__.choose object at 0x00000000022A5F28>>
                    print(type(getattr(self,cmd)))
                    # <class 'method'>
                    getattr(self,cmd)() # 运行方法
                else:
                    print('输入有误')
    
        def load(self):
            print('load')
        def down(self):
            print('down')
    
    obj = choose()
    print(type(obj.load))   # <class 'method'>
    obj.run()
  • 相关阅读:
    BZOJ3752 : Hack
    XIV Open Cup named after E.V. Pankratiev. GP of SPb
    XIII Open Cup named after E.V. Pankratiev. GP of Ukraine
    BZOJ2087 : [Poi2010]Sheep
    BZOJ2080 : [Poi2010]Railway
    BZOJ2082 : [Poi2010]Divine divisor
    Moscow Pre-Finals Workshop 2016. National Taiwan U Selection
    XIII Open Cup named after E.V. Pankratiev. GP of Asia and South Caucasus
    XIII Open Cup named after E.V. Pankratiev. GP of Azov Sea
    XIII Open Cup named after E.V. Pankratiev. GP of SPb
  • 原文地址:https://www.cnblogs.com/ludingchao/p/11950010.html
Copyright © 2020-2023  润新知