反射
反射是一个很重要的概念,它可以把字符串映射到实例的变量或者实例的方法然后可以去执行调用、修改等操作。
通过字符串操作类对象 或者 模块中的相关成员的操作
#hasattr() 检测对象/类是否有指定的成员
#getattr() 获取对象/类成员的值
#setattr() 设置对象/类成员的值
#delattr() 删除对象/类成员的值
attr是属性英文的前几个字母,属性指的是类中类变量、实例变量和方法。
但是要注意不能是私有的,如果你的变量是以“_”开头,那将无法获取。
反射常常用在动态加载模块的场景中。
一、 通过字符串反射类对象中的成员
class Father(): pass class Mother(): pass class Children(Father,Mother): eye = "蓝色的" weight = "1吨" def eat(self): print("小孩下生会喝奶") def drink(self): print("小孩下生喜欢喝勇闯天涯...") def __la(self): print("小孩自动啦,无法控制") obj = Children()
(1)hasattr() 检测对象/类是否有指定的成员
#对象 res = hasattr(obj,"eye") print(res) #类 res = hasattr(Children,"eat123") print(res)
hasattr()可以检测对象或类中是否包含某成员,第一个参数是类或者对象,第二个参数是 具体的成员。第二个参数以字符串方式写入
如果类或对象能调用该成员,返回真。不能调用返回假。从而判断是否有该成员
不能检测到类或对象的私有属性或方法
类中有私有成员方法
但却检测不到
(2)getattr() 获取对象/类成员的值
#对象
res = getattr(obj,"weight") print(res)
#如果获取的值不存在,可以设置第三个参数,防止报错。第三个参数当成员不存在时返回该值,防止程序报错
如果不设置,就报错
res = getattr(obj,"weight123","抱歉这个值不存在") print(res)
设置了,如果成员不存在,就返回设置的默认值
#类 反射方法
#通过类进行反射 (反射出来的是普通方法)
func = getattr(Children,"drink") print(func) func(1)
通过类反射出来的方法,如果该方法是绑定到对象方法,调用时要带参数,否则报错
#通过对象进行反射 (反射出来的是绑定方法) 调用时不用携带参数
func = getattr(obj,"drink") print(func) func()
打印方法,前面有bound method的是绑定方法
#综合案例
strvar = "eat11" if hasattr(obj,strvar): func = getattr(obj,strvar) func() else: print("抱歉,该成员不存在")
(3) setattr() 设置对象/类成员的值 setattr()方法里面三个参数。第一个参数是类或对象,第二个是成员方法或成员属性名,第三个是值
#对象
setattr(obj,"skin","黑人") print(obj.skin)
#类
setattr(Children,"skin","土耳其人") print(Children.skin) print(obj.skin)
通过类反射设置的成员属性,对象能调用,但不是对象的成员。是类的成员
(4) delattr() 删除对象/类成员的值
# 对象 delattr(obj,"skin") print(obj.skin)
# 类 delattr(Children,"skin") print(Children.skin)
二、通过字符串反射模块中的成员
sys.modules 返回一个系统字典,字典的键是加载的所有模块 '__main__': <module '__main__' from '/mnt/hgfs/python32_gx/day25/2.py'> 字典中的__main__这个键对应的是该文件的模块对象; def func1(): print("我是func1方法") def func2(): print("我是func2方法") def func3(): print("我是func3方法") import sys print(sys.modules) # 系统字典 module = sys.modules["__main__"] print(module) res = getattr(module,"func1") print(res) sys.modules返回一个系统字典 __main__ 这个键的值 对应的就是当前文件的模块对象
可以通过getattr()方法获取当前模块中的成员方法或成员属性。并且可以调用
综合案例 : (通过字符串反射模块中的成员)
while True: strvar = input("请输入你想要使用的功能:") if hasattr(module,strvar): func = getattr(module,strvar) func() elif strvar.upper() == "Q": print("再见") break else: print("没有该成员~!")