I’m going to oversell the with statement for a moment what was the most important invention in the history of computer languages… —Raymond Hettinger
哦,尊贵的尼古拉斯·with先生,看看这吊炸天的评论,看在上帝的面上,我今天就要把你一探究竟。
Python 中的 with 语句支持用上下文管理器来定义运行时的上下文环境。上下文管理器允许一个由用户定义的类在语句执行前执行上文定义的环境,并在语句执行结束后退出。
上下文管理器是由一对方法(__ enter __, __ exit __)实现的,为了达成上述的目的,我们先要来了解 这两种特殊方法是怎么运作的。
首先让我们来看一个示例:
class Open_file:
def __enter__(self):
f = open('123.py','w')
f.write("b'\xe6\x88\x91\xe5\x96\x9c\xe6\xac\xa2\xe4\xbd\xa0'") #_1
print("打开并写入文件")
return "sny_sny" #_2
def __exit__(self,exc_type,exc_value,traceback): #_3
f.close() #_4
print("文件已经关闭!")
if exc_type is OSError:
return True #_5
with Open_file() as sny: #_6
print(sny) #_7
print("hello world")
输出:
正在打开文件
sny_sny
hello world
文件已经关闭!
#_1 : 我们在新打开的文件写入一段utf_8字节序列。
#_2 : 这里我们让 __ enter __方法返回一个字符串,她会绑定在with语句中as后面的变量上
#_3 : __ exit __ 方法中有三个位置参数, 下面介绍一下他们分别接受的参数:
exc_type : 异常类,如(ZeroDivisionError, OSError).
exc_value : 异常实例,有时候会传给异常的构造方法,这些参数可以用 exc_value.args来获取。
traceback : traceback 对象。
如果with语句中运行正常,这三个参数均返回None。
#_4 : 在 __ exit __ 方法中将文件关闭。
#_5 : 这里我们返回了True,就是告诉解释器抑制这个异常。否则这三个参数任何一个出现问题都会返回假值并向上冒泡。 也就是说这个异常会替代所有在with语句块中出现的异常。
#_6 : 我们执行with语句时,先执行 __ enter __ 方法里的代码,然后执行 with语句代码块里面的内容,最后执行 __ exit __ 方法里的内容。
#_7 : 这里打印as 后面的变量,发现正是 __ enter __ 方法返回的值。
我们在处理这种代码的时候,以前我们会使用异常处理语句。
f = open('123.py','w')
try:
f.write('34567')
except OSError:
....
finally:
f.close()
现在我们有更加优雅的with语句了:
with open('123.py','w') as f:
f.write('34567')
>>>f.closed
>>> True
可以看到,文件对象已经在执行完with语句后关闭了。
我们可以这么理解: 在上下文管理器中,__ enter __ 方法替代了异常处理语句的 try 语句,__ exit __ 方法 替代了except 和 finally 语句。
了解了with语句后,你能不能搞出骚操作呢?能否利用with创造出更方便的用法呢?没准python下一个版本里就有你的骚操作哦~