一、什么是反射??
在面向对象的思想中,把对象能够访问、查询、修改自身的状态或行为称为“反射”。
二、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('处理其他的逻辑')
好处二:动态导入模块(基于反射原理,获取当前的模块的成员)