python反射
python的反射是基于字符串的形式去对象(模块)中操作其成员。此操作是动态的,常用于web开发中url参数中对应模块或者函数的反射。
下面开始具体说明:
- 场景需求:
我的python脚本中有一百个函数,当前端页面被访问到之后,针对特定的url 我后端有特定的函数进行处理,我该如何判断这个URL需要后端那个函数来处理呢?写if判断?别闹了。一百多个呢,那执行效率会有多慢。看下面代码:
def f1(): print("f1") def f2(): print("f2") def f3(): print("f3") res = input("请输入url: ") if res == 'f1': f1() elif res == 'f2': f2() elif res == 'f3': f3() else: print("404") 执行结果: 请输入url: f1 f1 请输入url: f2 f2 请输入url: f3 f3 请输入url: adasd 404
现在是定义了3个函数,如果100个的,我得写100个if判断,那不疯了。。。
下面耍个小聪明,使用dict映射来做
def f1(): print("f1") def f2(): print("f2") def f3(): print("f3") func_map = { 'f1':f1, 'f2':f2, 'f3':f3, } res = input("请输入url: ") if res in func_map: func_map[res]() else: print('404') 输出结果: 请输入url: f1 f1 请输入url: f2 f2 请输入url: f3 f3 请输入url: asdad 404
发现还是很麻烦。字典需要写很长影射,而且后期我加一个函数,还得在字典中手动添加对应的影射关系,万一写错了。就悲催了。。。。下面反射就出来了,就可以很好解决此问题!
- 反射getattr处理
class getfunc(): def f1(self): print("f1") def f2(self): print("f2") def f3(self): print("f3") res = input("请输入url: ") obj_func = getfunc() func = getattr(obj_func,res) func() 输出结果: 请输入url: f1 f1 请输入url: f2 f2 请输入url: f3 f3 请输入url: f4 Traceback (most recent call last): File "反射.py", line 55, in <module> func = getattr(obj_func,res) AttributeError: 'getfunc' object has no attribute 'f4'
这里我们使用的是类的作法,先创建一个类,将所有函数放在类里。在调用前先实例化该类,不论类里有多少个函数,直接根据输入内容通过getattr调用类里的函数。这样后期不管添加多少函数,只要前端能调用符合要求,则都会被调到。
发现最后一个怎么报错?原来并没有匹配到f4这个函数。反射也提供了检查功能,类似于检查一个字典是否存在某个key一样。下面说明一下反射的基本操作类型
- 反射的操作类型:
- getattr() 查找
- setattr() 设置
- hasattr() 判断
- delattr() 删除 接着上面的类说明操作类型的用法:
class getfunc: def __init__(self): self.test = '1234' def f1(self): print("f1") def f2(self): print("f2") def f3(self): print("f3") foo = getfunc() print(hasattr(foo,'f1')) 判断是否有f1 print(hasattr(foo,'f5')) 判断是否有f5 print(setattr(foo,'f5','f1')) 设置f5为f1 print(getattr(foo,'f5')) 判断是否有f5 print(delattr(foo,'test')) 删除test print(hasattr(foo,'test')) 判断是否有test 运行结果: True False None f1 None False
同样模块也支持动态导入,看下面说明:
- 反射模块
模块动态导入使用__import__方法
定义一个模块:fanshe def login(): print('登录页面') def logout(): print('退出页面') def home(): print("主页面") 下面是调用代码: inp = input("请输入url:") m,f = inp.split('/') try: obj = __import__(m) except: print("404") sys.exit() if hasattr(obj,f): func = getattr(obj,f) func() else: print("404") 执行结果: 请输入url:fanshe/login 登录页面 请输入url:fanshe/logout 退出页面 请输入url:fanshe/home 主页面
反射太强大了。