4.4.2 自定义上下文
with
块的本质是为了简化 try finally
语句,以上一节的代码为例,跟在 with
后面的 open()
函数会返回一个对象,它是 TextIOWrapper
类的实例,我们把它称为上下文管理器,上下文管理器需要实现 enter和
exit` 方法。
__enter__
方法的返回值可以用 as
来引用,这里上下文管理器的 __enter__
方法的返回值是 self
,所以以下两种写法中的文件句柄 fp
是等价的:
第一行中的 fp
可以理解为第二行中的上下文管理器,也就是 with
后面表达式的返回值。而 as
后面的 fp
则是上下文管理器的 __enter__
方法的返回值,由于这里返回的是 self
,所以两者恰好相同。
无论以哪种方式退出 with
块(正常结束或者因为抛出异常而退出),都会调用上下文管理器的 __exit__
方法。注意,这里不是 __enter__
方法返回值的 __exit__
方法。这一点很好理解,因为前者一定实现了 __enter__
方法,但后者不一定。
了解了上下文的概念后,我们可以自定义一个上下文,其实也就是定义一个实现了 __enter__
和 __exit__
方法的类:
在进入上下文的时候,我们用自定义的方法替换了系统的标准输出,所以上下文中所有的输出都是倒序的。直到上下文结束时才换回来。
__exit__
方法有三个参数,分别表示异常的类型,异常的实例,以及发生异常处的调用栈。如果在 with
块中发生了异常,异常处后面的代码都不会执行。__exit__
方法如果返回 True,表示异常已经被正确处理,否则异常会向上冒泡到 with
代码块外面。
Last updated