反射

一、什么是反射??

  在面向对象的思想中,把对象能够访问、查询、修改自身的状态或行为称为“反射”。

二、python中的反射

  Python思想:一切事物皆为对象。

  在python中,可以通过字符串的的形式来操作对象的属性。这种行为称之为python中的反射。

三、python实现反射(自省)的手段:

  通过4个内置函数来实现:hasattr(object,name)      getattr(object,name,default=None)   setattr(x,y,v)   delattr(x,y)

  • hasattr(object,name)

复制代码
#判断object中有没有一个name字符串对应的方法或属性
存在返回True,不存在返回False
def delattr(x, y): # real signature unknown; restored from __doc__
    """
    Deletes the named attribute from the given object.

    delattr(x, 'y') is equivalent to ``del x.y''
    """
    pass
复制代码
  • getattr(object,name,default=None)

复制代码
def getattr(object, name, default=None): # known special case of getattr
    """
    getattr(object, name[, default]) -> value

    Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
    When a default argument is given, it is returned when the attribute doesn't
    exist; without it, an exception is raised in that case.
    """
    pass
# 其中default表示没有找到该属性时所返回的提示。。。
复制代码
  • setattr(object,name,value)

复制代码
def setattr(x, y, v): # real signature unknown; restored from __doc__
    """
    Sets the named attribute on the given object to the specified value.

    setattr(x, 'y', v) is equivalent to ``x.y = v''
    """
    pass
复制代码
  • delattr(x,y)

复制代码
def delattr(x, y): # real signature unknown; restored from __doc__
    """
    Deletes the named attribute from the given object.

    delattr(x, 'y') is equivalent to ``del x.y''
    """
    pass
复制代码

注意:不仅仅是实例对象才能使用反射,类本身也是对象,所以类也可以用反射,即类也可以作为object参数参入到上述四个函数中去。例如:

复制代码
class Foo(object):
 
    staticField = "old boy"
 
    def __init__(self):
        self.name = 'wupeiqi'
 
    def func(self):
        return 'func'
 
    @staticmethod
    def bar():
        return 'bar'
 
print getattr(Foo, 'staticField')
print getattr(Foo, 'func')
print getattr(Foo, 'bar')

类也是对象
复制代码

再如,文件再python中也被看作是对象,所以一个文件也能用上述四种方法来操作。

 

复制代码
#新建一个a.py文件,该文件下定义两个变量x和y
x=111                
y=222                
import sys           
obj1=sys.modules[__name__]#__name__当前程序所在的模块的名称
print(hasattr(obj1,'z')) #如果能找到名为x的属性,返回True,这里返回的是True
复制代码

 四、为什么使用“反射”

好处一:实现可插拔机制

假设场景:有两个文件需要同时被开发,但是其中一个文件开发进度较慢,可能会影响到另一个文件的开发,这是利用“反射”机制,可以先避开另一个文件的开发进度。。。

class FtpClient:
    'ftp客户端,但是还么有实现具体的功能'
    def __init__(self,addr):
        print('正在连接服务器[%s]' %addr)
        self.addr=addr
复制代码
#from module import FtpClient
f1=FtpClient('192.168.1.1')
if hasattr(f1,'get'):
    func_get=getattr(f1,'get')
    func_get()
else:
    print('---->不存在此方法')
    print('处理其他的逻辑')
复制代码

好处二:动态导入模块(基于反射原理,获取当前的模块的成员)

posted @ 2019-09-17 11:13  汉魂县令  阅读(120)  评论(0编辑  收藏  举报