反射使得程序具有在运行时动态修改自己的结构和行为的能力。比如导入模块、调用函数等等,这些都是python的反射机制,是一种编程方法、设计模式的体现,凝聚了高内聚、松耦合的编程思想,不能简单的用执行字符串来代替。
python的四个重要内置函数:getattr、hasattr、delattr和setattr较为全面的实现了基于字符串的反射机制。他们都是对内存内的模块进行操作,并不会对源文件进行修改。
内建函数:
getattr(object, name[, default])
参数:
- object – 对象。
- name – 字符串,对象属性。
- default – 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError。
class A(object):
bar = 1
def my_function(name):
print('hell0 : ', name)
a = A()
# 属性部分
print(getattr(A,'bar'))
print(getattr(A,'bar0',1000)) # 设置默认值
print(getattr(A,'bar1')) # 不设置默认值
1
1000
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
in
7 print(getattr(A,'bar'))
8 print(getattr(A,'bar0',1000)) # 设置默认值
----> 9 print(getattr(A,'bar1')) # 不设置默认值
AttributeError: type object 'A' has no attribute 'bar1'
# 函数部分
print(getattr(A,'my_function')('my_function'))
hell0 : my_function
None
这就是python的反射,它的核心本质其实就是利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动
如果指定的对象拥有指定的属性,则 hasattr() 函数将返回 True,否则返回 False。
print(hasattr(A,'bar'))
print(hasattr(A,'bar1'))
print(hasattr(A,'my_function'))
True
False
True
setattr(object, attribute, value)
参数信息:
# 给对象 A 设置一个新的 age 属性
setattr(A,'age',40)
print(getattr(A,'age'))
# 修改对象 A 的 bar 属性值
setattr(A,'bar',40)
print(getattr(A,'bar'))
40
40
delattr(object, attribute)
参数信息:
# 删除已有的属性值
print("删除之前:", getattr(A,'bar'))
delattr(A, 'bar')
print("删除之后:", getattr(A,'bar'))
删除之前: 40
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
in
2 print("删除之前:", getattr(A,'bar'))
3 delattr(A, 'bar')
----> 4 print("删除之后:", getattr(A,'bar'))
AttributeError: type object 'A' has no attribute 'bar'
# 删除有有的属性值
delattr(A, 'bar1')
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
in
1 # 删除有有的属性值
----> 2 delattr(A, 'bar1')
AttributeError: bar1
通过__import__
函数,我们实现了基于字符串的动态的模块导入。
最关键的是obj = __import__(modules)
这一行,它让程序去导入了modules
这个变量保存的字符串同名的模块,并将它赋值给obj
变量。
obj = __import__(路径 + modules, fromlist=True)
# 注意fromlist参数
本文的核心主题是如何利用字符串驱动不同的事件,比如导入模块、调用函数等等,这些都是python的反射机制,是一种编程方法、设计模式的体现,凝聚了高内聚、松耦合的编程思想,不能简单的用执行字符串来代替。