反射
反射
有时候我们会碰到这样的需求,需要执行对象的某个方法,或是需要对对象的某个字段赋值,而方法名或是字段名在编码代码时并不能确定,需要通过参数传递字符串的形式输入。举个具体的例子:当我们需要实现一个通用的DBM框架时,可能需要对数据对象的字段赋值,但我们无法预知用到这个框架的数据对象都有些什么字段,换言之,我们在写框架的时候需要通过某种机制访问未知的属性,这个机制被称为反射
python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。
# hasattr(obj,str_name) 判断一个对象里是否有对应的str_name字符串属性 #getattr(obj,str_name) 根据字符串str_name去获取obj对象的对应属性的内存地址 # setattr(obj,'y',v ) Sets the named attribute on the given object to the specified value.将给定对象上的命名属性设置为指定的值 setattr(x, 'y', v) is equivalent to ``x.y = v'' #delattr(obj,str_name) 删除obj对象的str_name字符串属性
def Talk(self): print("%s is talking..."%self.name) class Dog(object): def __init__(self,name): self.name=name def eat(self,food): print("%s is eating %s"%(self.name,food)) d=Dog('小黑') choice=input(">>:").strip() if hasattr(d,choice): # func=getattr(d,choice) # func('something') delattr(d,choice) else: # setattr(d,choice,Talk) 添加动态属性 # func=getattr(d,choice) # func(d) setattr(d,choice,None) #添加静态属性 print(getattr(d,choice)) print(d.choice)
from wsgiref.simple_server import make_server class Handler(object): def index(self): return 'index' def news(self): return 'news' def RunServer(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) url = environ['PATH_INFO'] temp = url.split('/')[1] obj = Handler() is_exist = hasattr(obj, temp) if is_exist: func = getattr(obj, temp) ret = func() return ret else: return '404 not found' if __name__ == '__main__': httpd = make_server('', 8001, RunServer) print "Serving HTTP on port 8000..." httpd.serve_forever()
结论:反射是通过字符串的形式操作对象相关的成员。一切事物都是对象!!!
import sys def s1(): print 's1' def s2(): print 's2' this_module = sys.modules[__name__] hasattr(this_module, 's1') getattr(this_module, 's2')
类也是对象
class Foo(object): staticField = "school" def __init__(self): self.name = 'Mike' def func(self): return 'func' @staticmethod def bar(): return 'bar' print(getattr(Foo, 'staticField')) print(getattr(Foo, 'func')) print(getattr(Foo, 'bar')) #执行结果 school <function Foo.func at 0x01A135D0> <function Foo.bar at 0x01A13618>
模块也是对象
def dev(): return 'dev'
""" 程序目录: home.py index.py 当前文件: index.py """ import home as obj #obj.dev() func = getattr(obj, 'dev') func()