Python中的with语句
2020-06-05 09:12 abce 阅读(292) 评论(0) 编辑 收藏 举报考虑下面的代码:
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