python反射机制
一、 应用场景
- 根据不同的场景运行不同的函数,可以将这种写入配置中,读取配置,运行对应的函数,这个时候获取的函数为字符串,如何运行该字符串呢?
二、 反射的定义
- 反射就是通过字符串的形式,导入模块;反射就是通过字符串的形式,导入模块;
- 通过字符串的形式,去模块寻找指定函数,并执行。
- 利用字符串的形式去对象中操作属性或者函数利用字符串的形式去对象中操作属性或者函数
- 一种基于字符串的事件驱动一种基于字符串的事件驱动
三、 类中实现
-
getattr(object, filed, default)
从对象object中获取field对象(可能为属性或者方法),如果不存在,则返回默认值default -
hasattr(object, field)
判断对象object中是否含有field对象,返回True/False -
setattr(object, field, value)**
object.field = value (赋值操作) -
delattr(object, field)**
删除对象的某个属性
上述四个函数中的filed均为字符串类型,用来表示对象的一个属性名或者方法名# coding=utf8 class A(object): static_name = 'static_name' # 静态属性 def __init__(self): self.name = 'name ' # 属性名 def func_name(self, name=''): self.name = name print name @staticmethod def static_func_name(self, name='11'): static_name = name print static_name
if __name__ == '__main__': print(hasattr(A, 'name')) # False print(hasattr(A(), 'name')) # True print(hasattr(A, 'static_name')) # True print(hasattr(A(), 'static_name')) # True print(hasattr(A, 'name')) # False print(hasattr(A(), 'name')) # True print(hasattr(A, 'static_func_name')) # True print(hasattr(A(), 'static_func_name')) # True
通过这个,也可以清晰的看出来类属性和对象属性的差别
if __name__ == '__main__': print(getattr(A, 'static_name', 'default_name')) # static_name print(getattr(A, 'name', 'default_name')) # default_name 这个没有取到,所以用了默认值,类属性和对象属性 print(getattr(A(), 'name', 'default_name')) # name print(getattr(A(), 'error_name', 'default_name')) # 'default_name' 这个没有渠道 getattr(A, 'static_func_name', 'f')(name='A.static_func_name()') # A.static_func_name() getattr(A(), 'func_name', 'f')(name='A.func_name()') # A.func_name() print(getattr(A(), 'func_name', None)) # <bound method A.func_name of <__main__.A object at 0x10c2f4910>> print(getattr(A, 'func_name', None)) # <unbound method A.func_name> 未找到的意思 相当于None值
回到第一个应用场景
- 首先,我们可以定义一个类或者模块,在类中定义不同场景下执行的不同的函数
- 然后将该函数和场景写成配置,{“场景”: “配置”}
- 在不同的场景下,读取配置,首先使用hasattr判断该函数是否存在,然后使用getattr执行该函数
- 如果想,类也可以配置,不过,所有场景写在一个固定类里面,等以后添加新的场景的时候,会容易配置一些
四、 模块中实现
- 动态导入一个模块名
import(‘module_name’) - 导入模块下的子模块
import(‘module_name’, fromlist = True)
五、 exec和eval
- exec(“print(‘hello’)”)
- eval(expression, globals=None, locals=None)
官方文档:https://www.programiz.com/python-programming/methods/built-in/eval
不推荐使用eval,会有安全问题x = 1 print(eval('x + 1'))
六、 扩展
-
对象的内建函数或者方法http://www.cnblogs.com/huxi/archive/2011/01/02/1924317.html
dir(A()) 返回A对象的函数和方法: ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'func_name', 'name', 'static_func_name', 'static_name'] dir(A) ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'func_name', 'static_func_name', 'static_name']
A.__doc__ # 类的描述信息 A.__name__ # 类名 A.__dict__ # 包含了模块里可用的属性名-属性的字典;也就是可以使用模块名.属性名访问的对象。 A.__dict__ = { '__module__': '__main__', 'static_name': 'static_name', '__dict__': < attribute '__dict__' of 'A' objects > , 'func_name': < function func_name at 0x10558e6e0 > , 'static_func_name': < staticmethod object at 0x1055a4360 > , '__weakref__': < attribute '__weakref__' of 'A' objects > , '__doc__': '\n\t\xe7\xb1\xbb\xe6\x8f\x8f\xe8\xbf\xb0\n\t', '__init__': < function __init__ at 0x10558e0c8 > }