美文网首页
嵌套,反射

嵌套,反射

作者: 山猪打不过家猪 | 来源:发表于2021-12-02 14:28 被阅读0次

    嵌套

    #coding:utf-8
    
    
    class School(object):
        def __init__(self,name,addr):
            self.name =name
            self.addr = addr
    
        def classes(self):
            print(f"到{self.name}该班级上课")
    
    
    class Teacher(object):
        def __init__(self,name,age,salary,school=None):
            self.name=name
            self.age = age
            self.__salary = salary
            self.school = school
    
    
    
    s1=School("蟹蟹学校","蟹窝")
    s2=School("猪猪学校","猪窝")
    t1= Teacher("大番薯",18,30000,s1) #给大番薯传入s1学校实例
    
    print(t1.school.name)
    print(t1.school.addr)
    t1.school.classes()
    >>>
    蟹蟹学校
    蟹窝
    到蟹蟹学校该班级上课
    

    类可以做为列表的元素,字典的key,value等传入

    #coding:utf-8
    
    class UserInfo:
        pass
    
    class Department:
        pass
    
    class StartCofig:
        def __init__(self,num):
            self.num=num
    
        def changeList(self,requests):
            print(self.num,requests)
    
        def run(self):
            self.changeList(999)
    
    
    class RoleCofig(StartCofig):
        def changeList(self,requests):
            print("666666666ROle")
    
    class AdminSite:
        def __init__(self):
            self._registry ={}
    
        def register(self,k,v):
            self._registry[k] =v(k)
    
    
    site1= AdminSite()
    
    site1.register(UserInfo,StartCofig)
    site1.register(Department,StartCofig)
    print(len(site1._registry))
    for k,row in site1._registry.items():
        row.run()
    
    

    反射

    根据字符串的形式去某个对象中操作他的成员

    基本用法
    
    class Teacher:
        def __init__(self,full_name):
            self.full_name =full_name
    
    t=Teacher('Egon Lin')
    
    # hasattr(object,'name')
    hasattr(t,'full_name') # 按字符串'full_name'判断有无属性t.full_name
    
    # getattr(object, 'name', default=None)
    getattr(t,'full_name',None) # 等同于t.full_name,不存在该属性则返回默认值None
    
    # setattr(x, 'y', v)
    setattr(t,'age',18) # 等同于t.age=18
    
    # delattr(x, 'y')
    delattr(t,'age') # 等同于del t.age
    

    获取方法名后,在进行调用

    
    class Person(object):
    
        def __init__(self,name,age):
            self.name = name
            self.age =age
    
        def aaa(self):
            print("干他")
    
    
    p1 = Person('egon',19)
    
    res1 = getattr(p1,'name')
    print(res1)
    res2 = getattr(p1,'aaa')
    res2()
    
    >>>
    egon
    干他
    
    

    getattr

    和getattr()的区别:getattr()直接获取,如果没有该方法或者没有该属性,会直接报错。所以,使用是通常通常配合hasattr()先判断是否有该方法,然后进行使用。且无法进行定制化操作
    例子:

    class Frob():
        pass
    
    f = Frob()
    print(getattr(f,'bn'))
    >>>
    AttributeError: 'Frob' object has no attribute 'bn'
    

    getattr():当用户试图访问不存在的属性时调用,你可以通过这个魔法方法来定义类的行为。和getattr()的区别就在于可以自定义无属性时候的操作
    例如:

    class Frob():
    
        def __getattr__(self, item):
            print("自定骚操作,干啥都行")
            return None
    
    f = Frob()
    print(f.nb)
    
    

    在看一个比较有意思的例子:

    
    class List:
        def __init__(self,seq):
            self.seq=seq
    
        def append(self, p_object):
            ' 派生自己的append加上类型检查,覆盖原有的append'
            if not isinstance(p_object,int):
                raise TypeError('must be int')
            self.seq.append(p_object)
    
        @property
        def mid(self):
            '新增自己的方法'
            index=len(self.seq)//2
            return self.seq[index]
    
        def __getattr__(self, item):
            print(item)  ##item是调用的方法名,只有在没有的时候才会触发
            print(self.seq)  ##传入的列表
            return getattr(self.seq,item)
    
        def __str__(self):
            return str(self.seq)
    
    l=List([1,2,3])
    
    l.insert(0,-123)
    print(l)
    
    

    例子解释:自定义的List类,传入的列表[1,2,3],实例化出l并且调用了该类没有的insert方法,如果没有getattr会直接报错,没有该方法,Pycharm里面也会飘黄,加了getattr_后,里面使用getattr()方法找到了 self.seq列表 内置方法的insert()方法,完成了切片!!!

    判断是否有方法在进行调用

    class Ftp:
        def put(self):
            print("Download now")
    
        def get(self):
            print('pull documents')
    
        def interaction(self):
            method_ftp = input(">>>: ").strip()
            if hasattr(self,method_ftp):
                getattr(self,method_ftp)()
            else:
                print("wrong ")
    
    
    obj=Ftp()
    obj.interaction()
    
    >>>
    >>>: ssss
    wrong 
    
    
    通过模块名称调用里面的类
    import sys
    
    
    wahaha = "娃哈哈"
    
    def aaa():
        print("aaaa")
    
    class Vvs:
        def bbb(self):
            print("我是bbb")
    
    
    print(sys.modules['test_base'])
    print(getattr(sys.modules['test_base'],'Wechat')) ##这样就拿到了模块test_base里面的Whechat类
    print(getattr(sys.modules['__main__'],'wahaha')) ##获取当前模块的wahaha属性
    print(getattr(sys.modules['__main__'],'aaa')) ##这获取当前模块aaa方法
    print(getattr(sys.modules['__main__'],'Vvs')) ##这获取当前模块Vvs类
    
    b123 =getattr(sys.modules['__main__'],'Vvs')()
    b123.bbb()
    

    反射的应用

    
    
    class Course:
        def __init__(self,name,price,period):
            self.name = name
            self.price = price
            self.period = period
    
    
    class Student:
        func_list= [
            {'text':'选课','option_name':'select_course','param_key':None},
            {'text':'查看课程','option_name':'show_select_course','param_key':None},
            {'text':'删除课程','option_name':'del_select_course','param_key':None}
    
        ]  
    
        def __init__(self,name):
            self.name = name
            self.course =[]
    
        def select_course(self,cls):
            pass
    
        def show_select_course(self,cls):
            for k,v in enumerate(cls):
                print(k,(v.name,v.price,v.period))
    
        def del_select_course(self,cls):
            pass
    
    
    def run():
        total_course_list = []
        for i in range(1,3):
            obj= Course(f"{i}语文课",90,9000) ##生成3门课程传入
            total_course_list.append(obj)
    
        student_info = input("请输入学生姓名:")
        print(student_info)
        stu= Student(student_info)  #学生类实例化
        for i,item in  enumerate(stu.func_list,1): #打印课程论列表,和自动生成课程序号
            print(i,item['text'])
    
        while True:
            num = int(input("请选择序号:"))   #输入课程序号
            num= num -1 #拿到序号
            row = stu.func_list[num] #从func_list列表里根据index取操作的列表
            name = row.get('option_name') #在操作列表里 获取对应的操作名
            func  = getattr(stu,name)  #通过反射,在stu类里面找到对应的方法
            func(total_course_list) #在该方法下传入参数 
    
    
    if __name__=='__main__':
        run()
    

    选课系统反射应用

    #coding:utf-8
    
    import pickle
    import logging
    import sys
    
    LOGPATH = r'选课系统\operation.log'
    
    
    class Course(object):
        def __init__(self, name, price, period):
            self.name = name
            self.price = price
            self.period = period
    
    
    class Student(object):
        opt_list = [('查看课程', 'show_courses'), ('选择课程', 'choose_course'),
                    ('查看以选择课程', 'show_selected'), ('退出', 'exit')]
        def __init__(self, name):
            self.name = name
            self.classes = []
        def show_courses(self):
            pass
        def choose_course(self):
            pass
        def show_selected(self):
            pass
        def exit(self):
            pass
        @staticmethod
        def create_obj(ret, logger):
            with open('stuinfo', 'rb') as f:
                while True:
                    try:
                        stu = pickle.load(f)
                        if stu.name == ret[0]:
                            obj = stu
                            return obj
                    except:
                        logger.error(f'学生{stu.name}查无此人信息,请检查{STUINFOPATH}')
    
    
    class Manager(object):
        opt_list = [('创建课程', 'create_course'), ('创建学生', 'create_student'),
                    ('查看课程', 'show_courses'), ('查看学生', 'show_students'),
                    ('查看学生和已选课程', 'show_stu_course'), ('退出', 'exit')]
        def __init__(self, name, logger):
            self.name = name
            self.logger = logger
        def create_course(self):
            pass
        def create_student(self):
            user = input('usename: ')
            pwd = '1234'
            stu = Student(user)
    
            with open('userinfo', mode='a', encoding='utf-8') as f:
                print(f'{user}|{pwd}|Student', file=f)
    
            with open('stuinfo', mode='ab') as f:
                pickle.dump(stu, f)
            self.logger.info(f'管理员{self.name}创建学生{user}')
    
        def show_courses(self):
            pass
        def show_students(self):
            pass
        def show_stu_course(self):
            pass
        def exit(self):
            pass
        @classmethod
        def create_obj(cls, ret, logger):
            return cls(ret[0], logger)
    
    
    def login():
        '''
        None
        :return: 登陆成功,返回用户名和身份;否则,返回false
        '''
        username = input('username:')
        password = input('password:')
        with open('userinfo',encoding='utf-8') as f:
            for line in f:
                user, pwd, ident = line.strip().split('|')
                if username == user and password == pwd:
                    return username, ident
        return False
    
    
    def initLog():
        fh = logging.FileHandler(filename=LOGPATH, mode='a', encoding='utf-8')
        ch = logging.StreamHandler()
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        fh.setFormatter(formatter)
        ch.setFormatter(formatter)
        logger = logging.getLogger()
        logger.setLevel(logging.DEBUG)
        logger.addHandler(fh)
        logger.addHandler(ch)
        return logger
    
    
    if __name__ == '__main__':
        logger = initLog()
        ret = login()   ##登陆权限判断,返回用户名,和用户权限组
        if ret:
            print(f'登录成功,{ret[0]}欢迎使用选课系统')
            cls_s = getattr(sys.modules['__main__'], ret[1])  ##通过反射 获取登陆后的学生类或者管理员类
            obj = cls_s.create_obj(ret, logger)  #类名.creat_obj进入到对应的不同类里的creat_obj方法
            for i, opt in enumerate(cls_s.opt_list, 1):
                print(i, opt[0])
            num = int(input('您需要选择的操作:'))
            if hasattr(obj, cls_s.opt_list[num-1][1]):
                getattr(obj, cls_s.opt_list[num-1][1])()
        else:
            print('登陆失败')
    
    

    相关文章

      网友评论

          本文标题:嵌套,反射

          本文链接:https://www.haomeiwen.com/subject/vddmnktx.html