反射是将字符串映射到实例变量或实例方法的一种机制
作用:
- 动态加载模块
- web框架的URL路由
作用场景:
- 你的队友封装了很多py文件,你负责根据不同需求调用不同模块
- 你写了一个类,其中封装了很多方法,这时你需要提供一个统一的入口供其他人调用(类似路由转发)
需要的函数:
- __import__()动态加载模块
- hasattr() 判断实例是否存在字符串对应的属性
- getattr()获取获取字符串对应的属性
- setattr()将字符串对应的已存在的属性添加到实例中
- delattr()删除实例中字符串对应的属性
实例1:
- 首先创建一个包src
- 然后在包里创建3个py文件
#包1:名字为func_001.py
class Func001(object):
def process(self):
print("Func001")
#包2:名字为func_002.py
class Func002(object):
def process(self):
print("Func002")
#包2:名字为func_003.py
class Func003(object):
def process(self):
print("Func003")
def new_method(self):#方法
print("我是新来的")
def main():
"""
动态导入模块,并创建类实例执行其中方法
"""
#1 动态导入func_001模块
func001_module=__import__("src.func_001",fromlist=True)#从src包下面找到func_001模块,fromlist=True保证程序能索引到func_001,否则只能到src
print(func001_module)
#1.1 判断是否存在对应类
if hasattr(func001_module,"Func001"):
#2 创建Func001类实例对象
func001=getattr(func001_module,"Func001")
#2.1 判断是否存在该方法
if hasattr(func001,"process"):
#2.1.1 获取process成员方法
func001_process=getattr(func001,"process")
#2.1.2 执行该方法
func001_process(func001)
else:
print("没有找到对应方法")
# 3 添加 向Func001中添加new_method方法
setattr(func001,"new_method",new_method)
#3.1 判断是否存在该方法
if hasattr(func001,"new_method"):
#3.1.1获取new_method成员方法
func001_new_method=getattr(func001,"new_method")
#3.1.2 执行该方法
func001_new_method(func001)
# 4. 删除func001新增方法
delattr(func001,"new_method")
print("是否存在新增方法:",hasattr(func001,"new_method"))
else:
print("没有找到对应的类")
if __name__=="__main__":
main()
Func001
我是新来的
是否存在新增方法: False
实例2:
class User(object):
def add(self):
print("新增一名同学")
def delete(self):
print("删除一名同学")
def update(self):
print("更新一名同学")
def select(self):
print("选择一名同学")
#传统的else if
def before_process(self,method):
if method=="add":
self.add()
elif method=="delete":
self.delete()
elif method=="update":
self.update()
elif method=="select":
self.select()
else:
print("无效调用")
#反射机制
def after_process(self,method):
"""
类似路由转发
:param method: str 待调用方法名
:return:
"""
if hasattr(self,method):
func=getattr(self,method)
func()
else:
print("无效调用")
if __name__=='__main__':
user=User()
user.before_process(method="add")
user.after_process(method="delete")