我真的懂with语句吗?
with语句在很早之前我们就已经说过了,但也只是简简单单地一笔带过——使用了with语句不必自己手动关闭文件。with语句这么重要,我却这么吊儿郎当,罪过啊,今天来我决定弥补一下过错,和大家一起重点学习一下with语句。
回顾
为了凑字数(高中写作文养成的好习惯),先来回顾一下with语句的简单用法。
with open(r'C:\Users\Admin\Desktop\test.txt','w') as f:
f.write('python小白联盟')
正题
在深入理解with语句之前,先来明确一下上下文管理器的概念:只要是实现了__enter__()、__exit__()方法的对象就可以称为是上下文管理器。
比如
classContext:
def__init__(self):
pass
def__enter__(self):
returnself
def__exit__(self,exc_type,exc_val,exc_tb):
pass
那么Context()就是上下文管理器,可以使用with语句
下面来说一下__enter__()和__exit__()
__enter__()
上面我写的__enter__()的返回值是实例化对象,其实它不一定非要返回实例化对象,当然,不返回就没啥意义了,__enter__()的返回值是as后面的那个玩意儿,我们来写段代码试验一下,眼见为实嘛
看到了吧,as后面那玩意确实是__enter__()的返回值
__exit__()
说完了__enter__(),咱再来说说__exit__()
无论with代码块的程序有没有出错,__exit__()方法都会执行,并且把错误信息显示出来
可以看出,__enter__()方法先执行,然后执行with代码块,如果代码块发生异常,__exit__()的代码依然会执行,并且可以自己手动把错误信息打印出来,如果with代码块没有发生异常,exc_type, exc_val, exc_tb三个值均为None。
利用__exit__()始终都会运行这一点,我们可以自己定义一个打开文件的方法。
装饰器实现上下文管理器
python还提供了使用装饰器的方法来实现上下文管理器,这种方法更加简单
yield之前的语句在__enter__()中运行,之后的语句在__exit__()中运行,yield后面的值为函数的返回值