Python with 关键字详解

在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


现在,当“with” 执行的时候,Python 会调用相应的 __enter__方法并且把返回的值赋值给as 后面的变量。Python会执行with下面的“some code”并且不管“some code”中发生了什么都会调用 __exit__  方法。

另外__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如有觉得我翻译的不对的地方欢迎指教 大笑








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值