理解Python的With语句

Python’s with statement provides a very convenient way of dealing with thesituation where you have to do a setup and teardown to make something happen. Avery good example for this is the situation where you want to gain a handler toa file, read data from the file and the close the file handler. 有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Pythonwith语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。 Without the with statement, one would write something along the lines of:如果不用with语句,代码如下:

file = open("/tmp/foo.txt")
data = file.read()
file.close()

There are two annoying things here. First, you end up forgetting to closethe file handler. The second is how to handle exceptions that may occur oncethe file handler has been obtained. One could write something like this to getaround this: 这里有两个问题。一是可能忘记关闭文件句柄;二是文件读取数据发生异常,没有进行任何处理。下面是处理异常的加强版本:

file = open("/tmp/foo.txt")
try:
    data = file.read()
finally:
    file.close()

While this works well, it is unnecessarily verbose. This is where with isuseful. The good thing about with apart from the better syntax is that it isvery good handling exceptions. The above code would look like this, when usingwith: 虽然这段代码运行良好,但是太冗长了。这时候就是with一展身手的时候了。除了有更优雅的语法,with还可以很好的处理上下文环境产生的异常。下面是with版本的代码:

with open("/tmp/foo.txt") as file:
    data = file.read()

while this might look like magic, the way Python handles with is moreclever than magic. The basic idea is that the statement after with has toevaluate an object that responds to an __enter__() as well as an __exit__()function. 这看起来充满魔法,但不仅仅是魔法,Pythonwith的处理还很聪明。基本思想是with所求值的对象必须有一个__enter__()方法,一个__exit__()方法。 After the statement that follows with is evaluated, the __enter__()function on the resulting object is called. The value returned by this functionis assigned to the variable following as. After every statement in the block isevaluated, the __exit__() function is called. 紧跟with后面的语句被求值后,返回对象的__enter__()方法被调用,这个方法的返回值将被赋值给as后面的变量。当with后面的代码块全部被执行完之后,将调用前面返回对象的__exit__()方法。 This can be demonstrated with the following example: 下面例子可以具体说明with如何工作:

#!/usr/bin/env python
# with_example01.py
 
class Sample:
    def __enter__(self):
        print "In __enter__()"
        return "Foo"
 
    def __exit__(self, type, value, trace):
        print "In __exit__()"
 
 
def get_sample():
    return Sample()
 
 
with get_sample() as sample:
    print "sample:", sample

When executed, this will result in: 运行代码,输出如下

bash-3.2$ ./with_example01.py
In __enter__()
sample: Foo
In __exit__()

As you can see, The __enter__() function is executed The value returned byit - in this case "Foo" is assigned to sample The body of the blockis executed, thereby printing the value of sample ie. "Foo" The__exit__() function is called. What makes with really powerful is the fact thatit can handle exceptions. You would have noticed that the __exit__() functionfor Sample takes three arguments - val, type and trace. These are useful inexception handling. Let’s see how this works by modifying the above example. 正如你看到的, 1. __enter__()方法被执行 2. __enter__()方法返回的值 - 这个例子中是"Foo",赋值给变量'sample' 3. 执行代码块,打印变量"sample"的值为 "Foo" 4.__exit__()方法被调用 with真正强大之处是它可以处理异常。可能你已经注意到Sample类的__exit__方法有三个参数- val, type trace这些参数在异常处理中相当有用。我们来改一下代码,看看具体如何工作的。

#!/usr/bin/env python
# with_example02.py
 
 
class Sample:
    def __enter__(self):
        return self
 
    def __exit__(self, type, value, trace):
        print "type:", type
        print "value:", value
print "trace:", trace
 
    def do_something(self):
        bar = 1/0
        return bar + 10
 
with Sample() as sample:
    sample.do_something()


Notice how in this example, instead of get_sample(), with takes Sample().It does not matter, as long as the statement that follows with evaluates to anobject that has an __enter__() and __exit__() functions. In this case,Sample()’s __enter__() returns the newly created instance of Sample and that iswhat gets passed to sample. 这个例子中,with后面的get_sample()变成了Sample()。这没有任何关系,只要紧跟with后面的语句所返回的对象有__enter__()__exit__()方法即可。此例中,Sample()__enter__()方法返回新创建的Sample对象,并赋值给变量sample When executed: 代码执行后:

bash-3.2$ ./with_example02.py
type: <type 'exceptions.ZeroDivisionError'>
value: integer division or modulo by zero
trace: <traceback object at 0x1004a8128>
Traceback (most recent call last):
  File "./with_example02.py", line 19, in <module>
    sample.do_something()
  File "./with_example02.py", line 15, in do_something
    bar = 1/0
ZeroDivisionError: integer division or modulo by zero

Essentially, if there are exceptionsbeing thrown from anywhere inside the block, the __exit__() function for theobject is called. As you can see, the type, value and the stack traceassociated with the exception thrown is passed to this function. In this case,you can see that there was a ZeroDivisionError exception being thrown. Peopleimplementing libraries can write code that clean up resources, close files etc.in their __exit__() functions. 实际上,在with后面的代码块抛出任何异常时,__exit__()方法被执行。正如例子所示,异常抛出时,与之关联的typevaluestack trace传给__exit__()方法,因此抛出的ZeroDivisionError异常被打印出来了。开发库时,清理资源,关闭文件等等操作,都可以放在__exit__方法当中。 Thus, Python’s with is a nifty construct that makes code a little lessverbose and makes cleaning up during exceptions a bit easier. 因此,Pythonwith语句是提供一个有效的机制,让代码更简练,同时在异常产生时,清理工作更简单。 I have put the code examples given here on Github. 示例代码可以在Github上面找到。

译注:本文原文见Understanding Python's "With" Statement





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python 的异步编程,async 和 await 是两个关键字,用于定义异步处理的函数和协程。下面是对这两个关键字的简单解释: - async:用于定义一个异步函数,一个异步函数可以被看作是一个协程。 - await:在协程等待另一个协程或者 Future 对象执行完成。 下面我来简单介绍一下 Python 异步编程的一些概念和使用方法。 协程 协程是一种用户态的轻量级线程,可以在其执行一些 IO 密集型的任务而不会阻塞整个应用程序。在 Python ,协程一般使用 async 关键字定义。协程使用 await 语句可以等待其他协程或者 Future 对象完成。 async/await async 和 await 是 Python 3.5 之后引入的关键字,用于定义协程和等待协程执行完成。async 定义协程,await 等待协程执行完成。 在协程,如果需要等待其他协程或者 Future 对象执行完成,可以使用 await 语句。await 语句会等待后面的协程或者 Future 执行完成,然后返回执行结果。 async with/async for 除了 async 和 await,Python 3.5 还引入了 async with 和 async for 语法。async with 用于定义异步上下文管理器,async for 则用于定义异步迭代器。 asyncio Python 3.4 引入了 asyncio 模块,用于支持异步编程。asyncio 模块提供了一些协程相关的 API,包括事件循环、协程、任务和 Future。 asyncio 的主要功能是提供一个事件循环,用于调度协程的执行。在事件循环,使用 run_until_complete 方法可以执行一个协程或者任务。 总结 async 和 await 是 Python 异步编程的两个关键字,用于定义协程和等待协程执行完成。在 Python 3.5 之后,async 和 await 成为了 Python 异步编程的标准,同时还引入了 async with 和 async for 语法。asyncio 模块提供了一些协程相关的 API,用于支持异步编程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值