python中的反射
一 概述
python中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象,都可以使用反射
用于反射的几种方法:
hasattr:hasattr(object, name)判断一个对象是否有name属性或者name方法。有就返回True,没有就返回False
getattr:getattr(object, name, default=None) 获取对象的属性或方法,没有则报错(可以设置默认返回值)。需要注意的是,如果获取的是对象的方法,返回的是方法的内存地址,我们可以添加()运行。实际
应用中:hasattr和getattr配套使用。
setattr:给对象的属性赋值,若属性不存在,先创建后赋值
delattr:删除该对象指定的一个属性,没有则报错
二 实例应用
2.1 对象应用反射
class Studnet(object): school = '社大' def __init__(self, name, age, score): self.name = name self.__age = age self.__score = score def get_age(self): print('%s 年龄为:%s' %(self.name, self.__age)) def get_score(self): print('%s 分数为:%s' %(self.name, self.__score)) s = Studnet('joe',18,80) # 检测是否含有某属性或方法 print(hasattr(s, 'name')) # True print(hasattr(s, 'get_age')) # True print(hasattr(s, 'xxx')) # True # 获取属性 n = getattr(s, 'name') print(n) func = getattr(s, 'get_age') print(func) # <bound method Studnet.get_age of <__main__.Studnet object at 0x000001D653866128>> func() # getattr(s, 'xxx') # 报错 AttributeError: 'Studnet' object has no attribute 'xxx' print(getattr(s,'xxx','不存在此属性')) # 设置属性 setattr(s, 'addr', '地球村') setattr(s, 'get_name', lambda self:self.name) print(s.__dict__) print(s.get_name(s)) # 删除属性 delattr(s,'addr') delattr(s,'get_name') # delattr(s,'xxx') # 不存在,则报错 print(s.__dict__)
2.2 类应用反射
class Studnet(object): school = '社大' def __init__(self, name, age, score): self.name = name self.__age = age self.__score = score def get_age(self): print('%s 年龄为:%s' %(self.name, self.__age)) def get_score(self): print('%s 分数为:%s' %(self.name, self.__score)) # 检测是否含有某属性或方法 print(hasattr(Studnet, 'name')) # False print(hasattr(Studnet, 'school')) # True # 获取属性 print(getattr(Studnet, 'get_age')) # <function Studnet.get_age at 0x000002E0558712F0> # 设置属性 setattr(Studnet, 'addr', '地球村') print(Studnet.__dict__) # 删除属性 delattr(Studnet,'addr') print(Studnet.__dict__)
2.3 模块应用反射
import sys def func1(): print('func1执行结果') def func2(): print('func2执行结果') this_module = sys.modules[__name__] # 获取当前模块(py文件) print(hasattr(this_module, 'func1')) # True getattr(this_module, 'func2')() # func2执行结果
# module_test.py文件 def func1(): print('module_test func1') def func2(): print('module_test func2') # 调用module_test.py import module_test print(hasattr(module_test,'func1')) # True getattr(module_test,'func1')() # module_test func1 getattr(module_test,'func2')() # module_test func2
三 反射之好处
3.1 实现可插拔机制
我们可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用。
class Foo(object): def __init__(self): pass def func1(self): print('required_module func1')
import required_module rm = required_module.Foo() if hasattr(rm,'func1'): get_func1 = getattr(rm,'func1') get_func1() else: print('不存在时执行此逻辑') if hasattr(rm,'func2'): get_func2 = getattr(rm,'func2') get_func2() else: print('不存在时执行此逻辑')
3.2 动态导入模块
import importlib
required_module = __import__('required_module') # 解释器内部使用调用方式
required_module = importlib.import_module('required_module') # 利用importlib导入,与__import__效果一致,建议使用
注:以上例子required_module.py文件与调用py文件在同一目录下

浙公网安备 33010602011771号