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
userinfo
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__)
 

原文地址:https://www.cnblogs.com/zhuangdd/p/12504487.html