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

  • 相关阅读:
    Window 命令
    HTTP 状态码
    Mysql基本用法-存储引擎-04
    Mysql基本用法-存储引擎-03
    Mysql基本用法-left join、right join、 inner join、子查询和join-02
    Mysql基本用法-01
    二进制编码-详细讲解
    JS操作文件
    PHP5接口技术入门
    PHP5中__get()、__set()方法
  • 原文地址:https://www.cnblogs.com/zhuangdd/p/12504487.html
Copyright © 2020-2023  润新知