在Python中with关键字很常用,相信你也经常遇见,例如:
if isinstance(self.commands, str):
with(settings(warn_only = True)):
sudo(self.commands, shell=False)
你或许会困惑with到底是个什么东西?其实with关键字并不难理解今天我们就来说说with statement
考虑下面这段代码:
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)
这种方法将上面的"do something" 提取出来作为一个函数 然后传给我们封装好了的controlled_execution并执行,这种方法看着有点别扭感觉,代码不是很清晰.
另外一种方式是使用“yield”
def controlled_execution():
set things up
try:
yield thing
finally:
tear things down
for thing in controlled_execution():
do something with thing
但是在 Python 2.4之前 yield是不允许在 try-finally中使用的,同样别扭的是用了一个loop 结构但是你知道你只执行这个代码一次。
所以考虑到前面两种解决方案的缺点,GvR 和 Python-dev 团队最后想出了一个通用的方法那就是with statement
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
另外__exit__方法还可以处理异常如返回一个正确的值,例如
def __exit__(self, type, value, traceback):
return isinstance(value, TypeError)
In Python 2.5, the file object has been equipped with __enter__ and__exit__ methods; the former simply returns the file object itself, and the latter closes the file:
在Python 2.5中,文件对象也可以和__enter__ and__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
至于Python with的源码实现要分析相应的源码才知道,我觉得应该和Java中得“语法糖”类似
以上内容翻译于 understanding python's with statement如有觉得我翻译的不对的地方欢迎指教