反射
描述
反射就是指在程序运行时,动态的去确定对象的类型,并且可以通过字符串的的形式去调用对应的属性,方法,导入模块,是一种基于字符串的事件驱动
举一个例子:
class Student: def __init__(self): self.name = 'mhy' self.price = '5000' obj1 = Student() content = input('>>>:') # 这里输入的name是字符串 # 如果不知道反射,我们平常都是这么根据输入调用的 if content == 'name': print(obj1.name) elif content == 'price': print(obj1.price)
但是上面的方法,我们如果要调用成百上千的个方法或者属性,不得死了,所以就有了反射这种方法
python提供了几个内置函数来解决这种事情getattr()
hasattr()
例如上面的例子,我们现在可以这样做,代码如下
对象的反射
getattr(对象,字符串形式属性或者方法名)
返回对象中属性名对应的值hasattr(对象,字符串形式属性或者方法名)
返回的是一个bool
值,判断对象中是否存在属性
反射属性
val = getattr(对象,'属性名')
val就是属性的值
class Student: def __init__(self): self.name = 'mhy' self.price = '5000' obj1 = Student() content = input('>>>:') if hasattr(obj1, content): # 判断obj1对象中是否存在该属性 ret = getattr(obj1,content) # 对象和输入的字符串 print(ret)
反射方法
方法的反射如果我们使用上面属性的反射的话,会有问题
比如属性是不需要加括号的,直接会返回值,但是方法不加括号只会返回内存地址,但是我们如何判断当前是否是个方法,还是个属性呢.这里要用到判断了
callable()
: 判断参数是否可调用
val = getattr('对象','方法名')
val
就是方法的地址
val()
==> 调用方法
代码如下:
class Student: def __init__(self): self.name = 'mhy' self.price = '5000' def show_name(self): print(self.name,self.price) obj1 = Student() content = input('>>>:') if hasattr(obj1, content): ret = getattr(obj1,content) if callable(ret): # 判断ret是否可调用,因为有可能是一个内存地址 ret() else: print(ret)
类的反射
class A: role = 'China' print(getattr(A,'role')) # 用类获取类的变量
模块的反射
# 模块的反射 import time print(time.time()) print(getattr(time,'time')())
反射本质:a.b ===== getattr(a,'b')
反射使用:
name = 'alex' age = 84 def func(): print('wahaha') class Student():pass import sys # 反射变量 ret1 = getattr(sys.modules[__name__],'name') ret2 = getattr(sys.modules[__name__],'age') # 反射函数 getattr(sys.modules[__name__],'func')() # 反射类 print(getattr(sys.modules[__name__],'Student'))
学生例子
class Studnet: opt_lst = [ ('查看可选课程', 'show_courses'), ('选择课程', 'choose_course'), ('查看已选课程', 'show_selected_course'), ('退出', 'quit') ] def __init__(self,name): self.name = name self.courses = [] def show_courses(self): print('查看一共有多少门课程') def choose_course(self): print('选择课程') def show_selected_course(self): print('查看已经选择的课程') def quit(self): print('退出') stu = Studnet('alex') for index,opt in enumerate(Studnet.opt_lst,1): print(index,opt[0]) num = int(input('请输入您要选择的操作序号:')) if hasattr(stu,Studnet.opt_lst[num-1][1]): getattr(stu,Studnet.opt_lst[num-1][1])()