您的位置:首页 > 编程语言 > Python开发

【原创翻译】理解python的with语句

2013-03-30 11:36 821 查看
【原创翻译,转载请注明译者及原文链接】

原文链接:
http://effbot.org/zone/python-with-statement.htm
从comp.lang.python和其他论坛来看,即使对于有经验的python程序员,Python 2.5的新with语句也让人有一些迷惑。

但实质上,一旦你理解了它所想要解决的问题,相较于python的其他内容,with表达式其实是相当简单的。看下面的代码:

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

在这里,“set things up”可以是打开一个文件,或者取得一些外部资源,而“tear things down”则将是关闭文件,或者释放,移除资源。try-finally的结构保证了“tear things down”这部分总会被执行,即使函数主体的代码不能正常结束。

如果你需要经常干这件事,那么把“set things up”和“tear things down”的代码放到一个库函数中并让其可以重复使用将会带来许多方便。当然你可以像这么干:

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

def my_function(thing):
do something

controlled_execution(my_function)

但这样有些罗嗦,尤其是当需要修改本地变量的时候。另外一种方法是使用仅一次的generator,并且使用for-in语句来“包装”代码:

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

for thing in controlled_execution():
do something with thing

但是yield在2.4及更早先的版本中甚至不允许被放到try-finally中。尽管这在2.5中被修正了,但这仍然显得有些古怪——你知道你仅仅想要执行某段语句一次,但你却使用了循环。

所以在尝试了很多方法之后,GvR和其python开发团队最终对后者进行了一个概括,使用对象而不是generator来控制外部代码的行为:

class controlled_execution:
def __enter__(self):
set things up
return thing
def __exit__(self, type, value, traceback):
tear things down

with controlled_execution() as thing:
some code

现在,当“with”语句被执行时,Python会首先计算类实例化的表达式(controlled_execution()),并基于表达式的值调用__enter__方法(这也被称为“上下文保护”,"context guard"),并且把__enter__函数的返回值赋给as后面的变量。Python随后会执行代码主体,不管主体代码发生了什么,保护(guard)对象的__exit__方法都会被调用。

作为额外的奖励,__exit__方法还可以监测异常,并且根据需要阻止异常或者对异常进行处理。要阻止异常,返回一个为true的值就可以。例如,如下的__exit_方法不会放过任何TypeError,但会让其他异常通过。

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

在Python2.5中,文件对象被包装了__enter____exit__方法;前者仅仅返回文件对象本身,后者则关闭文件:

>>> f = open("x.txt")
>>> f
<open file 'x.txt', mode 'r' at 0x00AE82F0>
>>> f.__enter__()
<open file 'x.txt', mode 'r' at 0x00AE82F0>
>>> f.read(1)
'X'
>>> 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("x.txt") as f:
data = f.read()
do something with data

这并不是很难,不是吗?

转载请注明译者及原文链接:)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: