Python之旅的第27天(复习、习题实现、__enter__、__exit__)

  最近工作开始有点忙了,感觉晚上学这个,白天工作精神还是不够用,今天正好是周五就看的少一点准备早点睡觉。晚上大致想了一下之前那个选课习题的思路,如果按照编程规范进行操作,还是需要一些思路的,大致目前的分析如下吧!

一、习题实现逻辑

先来个框架:   

  三个视图:学员视图 讲师视图 管理视图  三个视图即为三个管理接口   

  五个角色:学校、学员、课程、讲师、班级  

  五个角色即需要定义5个类 把要求对应成自己看懂的话:   

    ① 创建北京、上海 2 所学校    分析:定义学校类,通过类去创建学校实例   

    ② 创建linux , python , go 3个课程 ,linuxpy 在北京开,go 在上海开  分析:定义课程类,通过课程类去创建课程实例    

    ③ 课程包含,周期,价格,通过学校创建课程   分析:课程类里要包含周期、价格  课程实例通过学校类去创建   

    ④ 班级关联课程、班级关联讲师  分析:可以创建班级的时候需输入关联的课程,创建讲师的时候需输入关联的班级;一个班级对应一个课程 一个班级对应一个讲师

    ⑤ 通过学校创建班级, 班级关联课程、讲师   分析:跟④一样   

    ⑥ 创建学员时,选择学校,关联班级  分析:定义学员类,创建时选择学校,选择班级,通过学校类创建学员实例,班级类里面要有包含学员的信息的字典   

    ⑦ 创建讲师角色时要关联学校  分析:之前一样,依然通过学校类去创建讲师实例   

    ⑧ 学员视图 可以注册, 交学费, 选择班级    分析:看⑥ 学员选择班级后,通过班级关联的课程,打印课程的学费   

    ⑨ 讲师视图, 讲师可以.....bala....bala      分析:讲师视图登录需要讲师名,通过讲师名可以找到对应的班级实例,班级实例里包含班级名,课程名,学员信息等       注:一个班级对应一个课程 一个班级对应一个讲师     

        一个课程可有多个班级     

        一个讲师可教授多个班级     

        一个学员可学习多个班级的课 分析下管理视图:         

        管理视图具有的功能创建讲师, 创建班级,创建课程,这些都是通过学校创建(即通过学校类的方法调用),除了创建以外我们还需要增加查询讲师、班级、课程的功能(查看相应的信息),管理视图要有6个功能 分析下讲师视图:         

        讲师视图可查看所授课的班级,班级学生信息  讲师视图具有2个功能 分析下学生视图:        

        学生视图,要选择学校,选择班级(显示班级的名称,课程,价钱),添加到对应的班级内 咋做数据库呢?!         

        大致就是这些,最好是能实现一下

二、__enter__   __exit__

  其实之前就是接触过关于文件句柄

  有两种形式:

    f = open( ' a.txt'  ,  'w+' ,   encoding = 'utf-8')

    with open('a.txt')   as   f

  两个其实是一个效果,但是直接open需要你自己关闭文件,对操作来说不是很方便,如果是with open就方便多了

  执行完自动关闭,而其能这么执行依靠的就是__enter__   __exit__两个方法

  上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法

class Open:
    def __init__(self,name):
        self.name=name

    def __enter__(self):
        print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
        # return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with中代码块执行完毕时执行我啊')


with Open('a.txt') as f:
    print('=====>执行代码块')
    # print(f,f.name)

上下文管理协议

  __exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行

class Open:
    def __init__(self,name):
        self.name=name

    def __enter__(self):
        print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with中代码块执行完毕时执行我啊')
        print(exc_type)
        print(exc_val)
        print(exc_tb)



with Open('a.txt') as f:
    print('=====>执行代码块')
    raise AttributeError('***着火啦,救火啊***')
print('0'*100) #------------------------------->不会执行

  如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行

class Open:
    def __init__(self,name):
        self.name=name

    def __enter__(self):
        print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with中代码块执行完毕时执行我啊')
        print(exc_type)
        print(exc_val)
        print(exc_tb)
        return True



with Open('a.txt') as f:
    print('=====>执行代码块')
    raise AttributeError('***着火啦,救火啊***')
print('0'*100) #------------------------------->会执行
class Open:
    def __init__(self,filepath,mode='r',encoding='utf-8'):
        self.filepath=filepath
        self.mode=mode
        self.encoding=encoding

    def __enter__(self):
        # print('enter')
        self.f=open(self.filepath,mode=self.mode,encoding=self.encoding)
        return self.f

    def __exit__(self, exc_type, exc_val, exc_tb):
        # print('exit')
        self.f.close()
        return True 
    def __getattr__(self, item):
        return getattr(self.f,item)

with Open('a.txt','w') as f:
    print(f)
    f.write('aaaaaa')
    f.wasdf #抛出异常,交给__exit__处理

练习:模拟Open

  两大优势:

    1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预

    2.在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处

今晚要早点就寝了,拜拜喽

原文地址:https://www.cnblogs.com/xiaoyaotx/p/12535942.html