zoukankan      html  css  js  c++  java
  • Python 面向对象之反射

    Python 面向对象之反射

    TOC

    • 什么是反射?
    • hasattr
    • getattr
    • setattr
    • delattr
    • 哪些对象可以使用反射
    • 反射的好处
    • 例子一
    • 例子二

    什么是反射?

     程序可以访问、检查和修改它本身的状态的行为的一种能力(自省)
     python中在面向对象中的反射:通过字符串的形式操作对象相关属性,就是通过字符串让对象自省自检是否有字符串表示的属性。python
    反射提供hasattr/getattr/setattr/delattr
    

    hasattr

    • hasattr(obj, 'string') 让obj自省自检有没有和string名符合的属性,有返回True,没有返回False。

    getattr

    • getattr(obj, 'string', None) 返回obj和string名相同的绑定方法。可以用来让一个变量引用这个返回结果,后面就可以call这个变量
      ,相当于call对象的绑定方法.如果没有,返回None,没有第三个参数则抛出异常

    setattr

    • setattr(obj, 'string', val) obj设置一个和string同名的的属性,并赋值为val。

    delattr

    • delattr(obj, 'string') 删除obj对象的‘string’的同名的属性。

    哪些对象可以使用反射

    • python中一切都是对象,所以都可以使用反射来进行自省
    • 类可以对类的共有属性,方法(绑定方法,非绑定方法)进行反射
    • 当前模块也可以进行反射。如:判定导入的模块是否有某个方法,有的化就进行调用。

    反射的好处

    • 实现可插拔机制。什么意思呢?就是可先判定某个对象(模块对象,类对象,对象等)是否有某个属性(是否插入),有则调用处理。
      没有(拔出)则走另一条逻辑。
    • 这样可以实现团队开发中,实现预定好接口,就算调用的接口没有具体完成,调用方也可以完成自己的逻辑。
    • 动态模块导入:a.import(模块名)函数 b. 使用importlib模块,使用importlib的import_module('模块名')
    • 动态导入模块使用场景:
      • a. 动态引用模块的变量,可以利用反射,切换其引用的模块,并使用模块中的属性。
      • b. 使用反射判断是否有对应属性,有则干嘛,没有则干嘛。 两种场景都是利用对象的反射来处理。核心就是利用字符串来驱动不同的事件,比如导入模块,调用函数等。
        这是一种编程方法,设计模式的提现,凝聚了高内聚、松耦合的编程思想,不能简单的用执行字符串来代替。反射和exec()和eval()不同。
        参考:http://www.cnblogs.com/yooma/p/8004788.html

    例子一

    class People(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def speak(self):
            print('%s is speaking' % self.name)
    
    
    obj = People('孙悟空', 22)
    act = input('悟空:').strip()
    if hasattr(obj, act):
        getattr(obj, act)()
        func1 = getattr(obj, act)
        func1()
    else:
        print('{} can not {}'.format(obj.name, act))
    

    例子二

    class BlackMedium(object):
        feature = 'Ugly'
    
        def __init__(self, name, addr):
            self.name = name
            self.addr = addr
    
        def sell_house(self):
            print('%s 黑中介卖房子啦!' % self.name)
    
        def rent_house(self):
            print('%s 黑中介租房子啦' % self.name)
    
    
    sb = BlackMedium('傻逼', '美帝')
    # 判定是否有属性
    print(hasattr(sb, 'sell_house'))
    print(hasattr(sb, 'rent_house'))
    print(hasattr(sb, 'test'))
    
    # 获取一个属性,并用一个变量引用,调用变量来执行
    func1 = getattr(sb, 'sell_house', None)
    func1()
    func2 = getattr(sb, 'rent_house')
    func2()
    # func3 = getattr(sb, 'test')
    # func3()
    
    
    # 新增一个属性
    setattr(sb, 'age', '100')
    print(sb.age)
    print(getattr(sb, 'age'))
    setattr(sb, 'talk', lambda self: print('来买房呀%s' % self.addr))  # 这个就不是绑定方法了
    sb.talk(sb)
    
  • 相关阅读:
    Boolean()类型转换
    ECMAscript 变量作用域
    jQuery 添加样式属性的优先级别
    css类选择器类名覆盖优先级
    巡风扫描器安装-windows部署
    atom无法安装插件的解决方法之一
    网络爬虫url跳转代码
    查看天气的代码
    三级地名菜单
    购物清单代码
  • 原文地址:https://www.cnblogs.com/ZJiQi/p/9051702.html
Copyright © 2011-2022 走看看