Python中的with语句

考虑下面的代码:

set things up
try:
do something
finally:
set things down

其中,set things up可以是打开一个文件、或获取一些外部资源;set things down可能是关闭文件、释放资源。try..finally..结构保证了set things down部分始终都会被执行,即使do something代码部分没有全部完成。

 

如果你经常要做类似的工作,可以将set things up、set things down代码放入到一个库函数中,从而可以重复利用。比如:

def controlled_execution(callback):
set things up
  try:
  callback(thing)
  finally:
  set things down

def my_function(thing):
do something

controlled_execution(my_function)

但是,这样显得有点啰嗦,尤其是需要修改本地变量。

 

另一种方式是使用generator,并使用for循环封装代码:

def controlled_execution():
set things up
try:
yield thing
  finally:
      set things down

for thing in controlled_execution():
do something with thing

(在2.4之前,try..finally..中不支持使用yield)。但是使用循环构建还是下的有点奇怪,当你只想执行一次的时候。

 

经过考量之后,Python团队引入了with,使用一个对象来代替generator来控制外部代码:

class controlled_execution:
  def __enter__(self):
      set things up
      return thing

  def __exit__(self, type, value, traceback):
      set things down

with controlled_execution() as thing:
  some code

执行with语句,Python会评估表达式,调用__enter__()方法,并将其返回值通过as返回给变量;然后,会执行some code;无论执行了什么,最后都会调用__exit()__方法。

这里__enter__()方法可以查看exception,并可以在必要时候采取行动。要想抑制异常,只需返回一个true值。例如,__exit()__方法允许所有TypeError,但允许所有其他异常通过:

def __exit__(self, type, value, traceback):
return isinstance(value, TypeError)

 

在python 2.5中,file对象已经实现了__enter__()方法和__exit__()方法,从而简化了返回文件对象自身,以及之后关闭文件:

>>> f=open('t.txt')
>>> f
<open file 't.txt', mode 'r' at 0x7f3bd78e86f0>
>>> f.__enter__()
<open file 't.txt', mode 'r' at 0x7f3bd78e86f0>
>>> f.read(1)
'j'
>>> f.__exit__(None,None,None)
>>> f.read(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file
>>>

因此,打开文件,处理内容,然后关闭文件,可以简单地这样完成:

with open("t.txt") as f:
  data = f.read()
  do something with data

 

原文地址:https://www.cnblogs.com/abclife/p/13047757.html