day20_2 反射
反射
:用字符串数据类型的变量名来访问这个变量的值
反射的方法: getattr hasattr setattr delattr
先来看看代码:
class Student: def __init__(self,name): self.name = name def check_course(self): print('check_course') def choose_course(self): print('choose_course') def choosed_course(self): print('查看已选择的课程') stu = Student() num = input('>>>') if num == 'check_course': stu.check_course() elif num == 'choose_course': stu.choose_course() elif num == 'choosed_course': stu.choosed_course()
#我们实例化了一个学生对象,当学生输入动作。返回他相应的学生类中的方法
但是观察代码,发现如果多一些类的方法,就需要写更多判断,代码量大,不够优雅
下面介绍反射优化代码
类的角度
类:静态属性 类方法 静态方法
调用类中的东西:
除了万能的.,我们还能用反射!
命名空间.XXX <==> getattr(命名空间,'XXX')
class Student: ROLE = 'STUDENT' @classmethod def check_course(cls): print('查看课程了') @staticmethod def login(): print('登录') #反射查看属性 print(Student.ROLE) # 类名.静态属性 查看属性 print(getattr(Student,'ROLE')) #反射查看属性 # 反射调用方法 # getattr(类名,‘方法名’)获取方法 ,然后方法() 就是调用方法 getattr(Student,'check_course')() # 类方法 getattr(Student,'login')() # 静态方法 ==》Student.login()
num = input('>>>')
if hasattr(Student,num):
getattr(Student,num)() # hasattr() 函数用于判断对象是否包含对应的属性
我们可以通过反射,用户输入的值来自接调用类中的方法! 而类名。变量是做不到的!
对象的角度:
方法和对象属性
class A(): def __init__(self,name): self.name = name def func(self): print('in func') a = A('alex') print(a.name) print(getattr(a,'name')) getattr(a,'func')()
模块的角度
别人写的代码
import os # 别人写好的python代码的结合 os.rename('__init__.py', 'init') # 把当前路径的__init__.py,文件名改成init getattr(os, 'rename')('init', '__init__.py') # ==> os.rename rename = os.rename rename2 = getattr(os, 'rename') rename2('__init__.py', 'init') # os.rename('__init__.py','init') rename('init', 'init2') # os.rename('init','init2')
自己的代码中的使用方法
def wahaha(): print('wahaha') def qqxing(): print('qqxing')
我想找到
自己模块中的内容 找到自己当前文件所在的命名空间
wahaha()方法
qqxing()方法
可以这么做:
import sys # sys 是一个模块,这个模块里的所有的方法都是和python解释器相关的 print(sys.modules) #这个方法 表示所有在当前这个python程序中导入的模块 print(sys.modules['__main__']) #找到当前py文件 my_file = sys.modules['__main__'] my_file.wahaha() # 'qqxing' my_file.qqxing() # 'wahaha' #调用方法 getattr(my_file,'wahaha')() getattr(my_file,'qqxing')()
反射总结啦:
hasattr,getattr
# 类名.名字 # getattr(类名,'名字') # 对象名.名字 # getattr(对象,'名字') # 模块名.名字 # import 模块 # getattr(模块,'名字') # 自己文件.名字 # import sys # getattr(sys.modules['__main__'],'名字')
最后做一个选课系统!有下面的需求:
# login
# 判断身份 并且根据身份实例化
# 根据每个身份对应的类 让用户选择能够做的事情
1 class Mananger: 2 operate_dic = [ ('创造学生账号', 'create_student'), 3 ('创建课程','create_course'), 4 ('查看学生信息','check_student_info'), 5 ] 6 def __init__(self,name ): 7 self.name = name 8 def create_stu(self): 9 print('创建学生账号') 10 def create_course(self): 11 print('创建课程') 12 def check_stu_info(self): 13 print('查看学生信息') 14 15 16 class Student: 17 operate_dic = [ 18 ('查看所有课程', 'check_course'), 19 ('选择课程', 'choose_course'), 20 ('查看已选择的课程', 'choosed_course') 21 ] 22 def __init__(self,name): 23 self.name = name 24 def check_course(self): 25 print('check_course') 26 def choose_course(self): 27 print('choose_course') 28 def choosed_course(self): 29 print('查看已选择的课程') 30 31 32 def login(): 33 username = input('user : ') 34 password = input('pwd : ') 35 with open('userinfo') as f: 36 for line in f: 37 user,pwd,ident = line.strip().split('|') # ident = 'Manager' 38 if user == username and pwd == password: 39 print('登录成功') 40 return username,ident
1 alex|123456|Manager 2 hezewei|666|Student 3 taibai|2222|Teacher
import sys def main(): usr, id = login() print('user,id :', usr, id) file = sys.modules['__main__'] cls = getattr(file, id) #Manager = getattr(当前文件,'Manager') obj = cls(usr) #实例化 print(obj) operate_dic = cls.OPERATE_DIC while True: for num, i in enumerate(operate_dic, 1): # 枚举 print(num, i[0]) choice = int(input('num >>>')) choice_item = operate_dic[choice-1] print(choice_item) getattr(obj, choice_item[1])() main()
好了,最后剩两个方法:
class A: def __init__(self,name): self.name = name a = A('alex') # 给属性赋值 # 对象.属性赋值方法 a.name = 'alex_SB' # 反射方法 getattr(a, 'name') # 得到a.name的值 alex_SB setattr(a, 'name', 'alex_SB') # 把a.name的属性设置为alex_SB print(a.name) print(a.__dict__) # 删除属性 del a.name print(a.__dict__) delattr(a, 'name') print(a.__dict__)