PythonPython全栈

27.Python之面向对象的反射

2020-03-11  本文已影响0人  免跪姓黄

Python之面向对象的反射

  1. 反射的定义

    • 通过字符串来操作类与对象的属性(attribute)、实例变量、绑定方法等操作,称之为反射。
  2. 反射的作用

    • 想通过变量的字符串类型的名字,直接调用变量的时候,就需要用到反射。
  3. 反射语法

    • 以下四个内置函数是专门通过字符串来操作类与对象属性的:

      • hasattr(object, 'name') 函数用于判断name在不在类object中,等同于print('name' in object.__dict__)
      • getattr(object, 'name', None) 函数用于返回一个对象属性值,等于调用 object.name ,如果没有属性或属性没有值,就返回None,一般getattr()会与hasattr()成对出现。
      • setattr(object, 'name_1', 'name_2') 函数用于修改属性的值。
      • delattr(object, 'name') 函数用于删除属性的值。
    • getattr() 语法:

      getattr(object, 'name')
      # object -- 对象。
      # 'name' -- 对象属性的字符串。
      
  1. 反射的使用方法(场景)

    • 反射对象的实例变量和绑定方法

      class User(object):
          '''
          定义一个用户类
          '''
          def __init__(self):
              self.username = '徐凤年'
              self.password = '123'
      
      # 实例化
      user = User()
      
      # 通过内置函数getatter()进行反射
      徐凤年 = getattr(user, 'username')
      print(徐凤年)  # 得到的是self.username的值
      
    • 反射类的属性和方法

      class User(object):
          a = 'Python'
          def __init__(self):
              pass
      
      user = User()
      res = getattr(user, 'a')
      print(res)  # Python
      
    • 反射模块中的所有变量

      from abc import ABCMeta, abstractclassmethod
      import sys
      
      class Payment(metaclass=ABCMeta):
          def __init__(self, name):
              self.name = name
          @abstractclassmethod
          def pay(self):
              pass
      
      class AliPay(Payment):
          def pay(self, amount):
              print(F'{self.name}通过支付宝支付:{amount}元')
      
      class WeChatPay(Payment):
          def pay(self, amount):
              print(F'{self.name}通过微信支付:{amount}元')
      
      class ApplePay(Payment):
          def pay(self, amount):
              print(F'{self.name}通过苹果支付:{amount}元')
      
      # 归一化设计:让调用者不用实例化对象
      def pay(name, payment_method, amount):
          # if payment_method == 'AliPay':
          #     obj = AliPay(name)
          #     obj.pay(amount)
          #
          # elif payment_method == 'WeChatPay':
          #     obj = WeChatPay(name)
          #     obj.pay(amount)
          #
          # elif payment_method == 'ApplePay':
          #     obj = ApplePay(name)
          #     obj.pay(amount)
      
          # 通过反射完成上面的代码:
          if hasattr(sys.modules['__main__'], payment_method):    # 判断是否有paymen,避免报错
              pay_name = getattr(sys.modules['__main__'], payment_method)    # 将字符串类型的payment_method转化成类名称
              if callable(pay_name):  #  判断pay_name是否可调用,避免报错
                  obj = pay_name(name)    # obj = payment_method(name)
                  obj.pay(amount)
      
      
      # 其他程序员调用归一化设计的支付接口
      pay('马云', 'AliPay', 10000)  # 马云通过支付宝成功支付:10000元
      pay('马化腾', 'WeChatPay', 10000)  # 马化腾通过微信成功支付:10000元
      pay('乔布斯', 'ApplePay', 10000)  # 乔布斯通过苹果成功支付:10000元
      
上一篇 下一篇

猜你喜欢

热点阅读