目录

  • 一、上下文管理协议
  • 二、模拟open
  • 三、优点


  • 我们知道在操作文件对象的时候可以这么写
with open('a.txt') as f:    '代码块'
  • 上述叫做上下文管理协议,即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)
出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量=====>执行代码块with中代码块执行完毕时执行我啊
  • __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)try:    with Open('a.txt') as f:        print('=====>执行代码块')        raise AttributeError('***着火啦,救火啊***')except Exception as e:    print(e)
出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量=====>执行代码块with中代码块执行完毕时执行我啊<class 'AttributeError'>***着火啦,救火啊***<traceback object at 0x1065f1f88>***着火啦,救火啊***
  • 如果__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 Truewith Open('a.txt') as f:    print('=====>执行代码块')    raise AttributeError('***着火啦,救火啊***')print('0' * 100)  #------------------------------->会执行
出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量=====>执行代码块with中代码块执行完毕时执行我啊<class 'AttributeError'>***着火啦,救火啊***<traceback object at 0x1062ab048>0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

二、模拟open

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__处理
<_io.TextIOWrapper name='a.txt' mode='w' encoding='utf-8'>

三、优点

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

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

©著作权归作者所有:来自51CTO博客作者wx5b1fd43180419的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 第11部分- Linux ARM汇编 执行分支
  2. 流程控制之if判断
  3. 流程控制之while循环
  4. 给我1万字,也讲不清Java内存排查。1万不行来2万~.~
  5. 想把Java代码写的更漂亮么?了解一下Try吧
  6. 解析Java横死之谜,气定神闲看花开花落
  7. 将java进程转移到“解剖台”之前,法医都干了什么?
  8. 工作累了,用java写个游戏吧!开源一款游戏引擎
  9. 一些好用的Java小库儿

随机推荐

  1. TextView 属性详解
  2. android开发之设置Edittext密码的方法
  3. 【拿来主义】Android反编译工具
  4. Android(安卓)判断Root的方法
  5. Android 线程优先级设置方法
  6. Google手机操作系统Android应用开发入门
  7. Android 数据库简单操作
  8. Android缓存理解
  9. Android(安卓)frameworks中Bn*和Bp*的区
  10. Android系统启动流程 -- android