• 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()
  • 相关阅读:
    Bootstrap 、AngularJs
    spring boot 随手记
    STOMP
    socket、web socket
    spring boot (2):spring boot 打包tomcat、tomcat 部署多个项目、服务器部署项目SSL 设置(阿里云)
    spring boot (1):初尝
    SOA、SOAP、RFC、RPC、IETF
    Django中级篇(上)
    面向对象进阶篇
    面向对象基础 反射
  • 原文地址:https://www.cnblogs.com/ludingchao/p/11950010.html
Copyright © 2020-2023  润新知