反射指的是一个对象应该具备,可以检测,修改,增加自身属性的能力
反射就是通过字符串操作属性
涉及四个函数,这四个函数就是普通的内置函数,没有双下划线,与print等在使用方法上没有区别
hasattr,getattr,setattr,delattr(他们的具体使用方法和作用见下列代码)
1 class Person: 2 def __init__(self,name,age): 3 self.name = name 4 self.age = age 5 6 p = Person('sxc',18) 7 8 if hasattr(p,'name'): # 判断某个对象是否存在某个属性 9 print(getattr(p,'name')) # 把这个值当做返回值返回出来 10 11 print(getattr(p,'gender',None)) # 如果没有这个值后面还可以赋予他一个默认值 12 13 setattr(p,'id',177) # 可以为该对象赋予新的属性 14 print(p.id) 15 16 delattr(p,'id') # 也可以删除的对象的属性 17 print(p.id)
使用场景:
反射其实就是对属性的增删查改,但是如果直接使用内置的__dict__来操作,语法繁琐,不好理解
如果是另一方提供的,无法判断是否是我需要的属性和方法
简单的框架设计
框架就是已经实现了最基础的构架,就是所有项目都一样的部分已经完成了。反射被称为框架的基石,框架的设计者不可能提前知道使用者的对象到底是怎么设计的,所以使用者提供给框架的对象必须通过判断验证之后才能正常使用,判断验证就是反射要做的事
需求:实现一个用于处理用户的终端指令的小框架
1 # 框架部分 2 def run(plugin): 3 while True: 4 cmd = input('请输入您的指令>>>:').strip() 5 if cmd == 'exit': 6 break 7 # 无法判断传入的参数,需要加入反射加以判断 8 if hasattr(plugin,cmd): # 取出对应的指令 9 func = getattr(plugin,cmd) 10 func() # 执行指令处理 11 else: 12 print('请输入正确的指令') 13 print('退出程序') 14 15 # 从系统配置文件中截取模块路径和类名 16 module_path, class_name = settings.CLASS_PATH.rsplit('.',1) 17 # 拿到模块 18 mk = importlib.import_module(module_path) 19 # 拿到类 20 cls = getattr(mk,class_name) 21 # 实例化对象 22 obj = cls() 23 # 调用框架 24 run(obj)