反射
描述
反射就是指在程序运行时,动态的去确定对象的类型,并且可以通过字符串的的形式去调用对应的属性,方法,导入模块, 是一种基于字符串的事件驱动
举一个例子:
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])()