【Python干货】`__enter__` 与 `__exit__` 的作用,以及与with语句的关系
01 python上下文管理协议
上下文管理器(context manager) 是 Python2.5 开始支持的一种语法,用于规定 某个对象的使用范围。一旦进入或者离开该使用范围,会有特殊操作被调用 (比如为对象分配或者释放内存)。它的语法形式是 with...as...
所谓上下文管理协议,就是咱们打开文件时常用的一种方法: with
__enter__(self):当with开始运行的时候触发此方法的运行__exit__(self, exc_type, exc_val, exc_tb):当with运行结束之后触发此方法的运行
exc_type如果抛出异常,这里获取异常的类型exc_val如果抛出异常,这里显示异常内容exc_tb如果抛出异常,这里显示所在位置
02 with语句
2.1 示例
相信大家都在文档处理的过程中使用过 with 语句。
1 | with open("example.txt") as file: |
如果不用 with 语句,等价于
1 | file = open("example.txt") |
从本质上看, with语句完成了偷偷地完成了两件事:
- 事先需要设置,
- 2.事后做清理工作。
2.2 with 如何工作
“事前设置,事后清理”,这看起来充满魔法,但不仅仅是魔法。Python对with的处理是基于是所求值的对象必须有一个__enter__()方法,一个__exit__()方法。
下面例子可以具体说明with如何工作:
1 | class Sample: |
2.3 with处理异常
with真正强大之处是它可以处理异常。可能你已经注意到Sample类的__exit__方法有三个参数value, type 和 trace。 这些参数在异常处理中相当有用。我们来改一下代码,看看具体如何工作的。
1 | class Sample: |
实际上,在with后面的代码块抛出任何异常时,__exit__()方法被执行。正如例子所示,异常抛出时,与之关联的type,value和stack trace传给__exit__()方法,因此抛出的ZeroDivisionError异常被打印出来了。开发库时,清理资源,关闭文件等等操作,都可以放在__exit__方法当中。



