美文网首页
嵌套,反射

嵌套,反射

作者: 山猪打不过家猪 | 来源:发表于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('登陆失败')

相关文章

  • 嵌套,反射

    嵌套 类可以做为列表的元素,字典的key,value等传入 反射 根据字符串的形式去某个对象中操作他的成员 基本用...

  • 夯实 Java 基础 - 反射

    夯实 Java 基础 - 反射 自嵌套 Fragment 懒加载文章至今已经已经一个星期过去了,说实话最近对于学习...

  • 嵌套规则

    块元素能嵌套所有元素p不能嵌套块,只能嵌套行内行内元素不能嵌套块元素行内可以嵌套行内,但是不能嵌套自己a可以嵌套任...

  • Sass/Scss--2

    八.嵌套-选择器嵌套 Sass 的嵌套分为三种: 选择器嵌套 属性嵌套 伪类嵌套 html 结构: 选中 h...

  • React-Native Context跨层级的组件通信

    如图:APP界面嵌套A嵌套B嵌套C嵌套D嵌套E嵌套F...... 场景一:从APP界面获取数据,需要F来显示,怎么...

  • [Python基础]D6 循环嵌套、函数基础

    while 循环嵌套 4.1 循环嵌套 while 嵌套就是:while 里面还有 while 4.2 循环嵌套演...

  • markdown test

    一级标题 二级标题 三级标题 嵌套列表嵌套列表嵌套列表嵌套列表嵌套列表嵌套列表 无序列表 无序列表 有序列表1 有...

  • Swift学习笔记十五之嵌套类型

    1、类型嵌套//可以在允许类型嵌套的类型中嵌套枚举、类、结构体,并且支持多层嵌套2、值类型的嵌套struct Ne...

  • 5/12day52_mybatis嵌套查询&缓存

    回顾 MyBatis嵌套查询&缓存 今日目标 一 MyBatis嵌套查询 1.1 什么是嵌套查询 嵌套查询就是将原...

  • 结构体嵌套

    普通结构体嵌套 普通结构体嵌套,嵌套结构体可以通过 .子变量.方法 的方式获取被嵌套的属性和方法 匿名嵌套 匿名嵌...

网友评论

      本文标题:嵌套,反射

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