with as python_python - with as的用法

news/2024/7/5 1:44:06

摘自:http://www.cnblogs.com/DswCnblog/p/6126588.html

With 是什么?

有一些任务可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。

如果不用with语句,代码如下:

file = open("/tmp/foo.txt")

data=file.read()

file.close()

这里有两个问题。一是可能忘记关闭文件句柄;二是文件读取数据发生异常,没有进行任何处理。下面是处理异常的加强版本:

file = open("/tmp/foo.txt")try:

data=file.read()finally:

file.close()

虽然这段代码运行良好,但是太冗长了。这时候就是with一展身手的时候了。除了有更优雅的语法,with还可以很好的处理上下文环境产生的异常。下面是with版本的代码:

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

data= file.read()

With 如何工作

这看起来充满魔法,但不仅仅是魔法,Python对with的处理还很聪明。基本思想是with所求值的对象必须有一个__enter__()方法,一个__exit__()方法。

紧跟with后面的语句被求值后,返回对象的__enter__()方法被调用,这个方法的返回值将被赋值给as后面的变量。当with后面的代码块全部被执行完之后,将调用前面返回对象的__exit__()方法。

下面例子可以具体说明with如何工作:

#!/usr/bin/env python#with_example01.py

classSample:def __enter__(self):print "In __enter__()"

return "Foo"

def __exit__(self, type, value, trace):print "In __exit__()"

defget_sample():returnSample()

with get_sample() as sample:print "sample:", sample

运行代码,输出如下

In __enter__()

sample: Foo

In__exit__()

正如你看到的,

1. __enter__()方法被执行

2. __enter__()方法返回的值 - 这个例子中是"Foo",赋值给变量'sample'

3. 执行代码块,打印变量"sample"的值为 "Foo"

4. __exit__()方法被调用

with真正强大之处是它可以处理异常。可能你已经注意到Sample类的__exit__方法有三个参数- val, type 和 trace。 这些参数在异常处理中相当有用。我们来改一下代码,看看具体如何工作的。

#!/usr/bin/env python#with_example02.py

classSample:def __enter__(self):returnselfdef __exit__(self, type, value, trace):print "type:", typeprint "value:", valueprint "trace:", tracedefdo_something(self):

bar= 1/0return bar + 10with Sample() as sample:

sample.do_something()

这个例子中,with后面的get_sample()变成了Sample()。这没有任何关系,只要紧跟with后面的语句所返回的对象有__enter__()和__exit__()方法即可。此例中,Sample()的__enter__()方法返回新创建的Sample对象,并赋值给变量sample。

代码执行后:

bash-3.2$ ./with_example02.py

type:value: integer divisionormodulo by zero

trace:Traceback (most recent call last):

File"./with_example02.py", line 19, in sample.do_something()

File"./with_example02.py", line 15, indo_something

bar= 1/0

ZeroDivisionError: integer divisionor modulo by zero

实际上,在with后面的代码块抛出任何异常时,__exit__()方法被执行。正如例子所示,异常抛出时,与之关联的type,value和stack trace传给__exit__()方法,因此抛出的ZeroDivisionError异常被打印出来了。开发库时,清理资源,关闭文件等等操作,都可以放在__exit__方法当中。

因此,Python的with语句是提供一个有效的机制,让代码更简练,同时在异常产生时,清理工作更简单。


http://lihuaxi.xjx100.cn/news/239531.html

相关文章

center os7 安装mysql

安装mariadb MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可。开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL闭源的潜在风险,因此社区采用分支的方式来避开这个风险。M…

对 makefile 中 .SECONDARY 的学习体会

上例子 LIBSfoo.gao bar.gao .INTERMEDIATE:$(LIBS) .SECONDARY:bar.gao all: $(LIBS) #pass foo.gao: echo $ touch $ bar.gao: echo $ touch $   make --dry-run 的结果: foo.gao touch foo.gao bar.gao touch bar.gao #pass rm foo.gao 可见,SECONDARY 确实起到…

我的第一个web_登陆我的第一个全栈Web开发人员职位

我的第一个webby Robert Cooper罗伯特库珀(Robert Cooper) 登陆我的第一个全栈Web开发人员职位 (Landing My First Full Stack Web Developer Job) This is the story of the steps I took to get my first job as a full stack web developer. I think it’s valuable to sha…

加了好友怎么还掉血_微信聊天窗口出现风险提醒,无法添加好友解决办法

再更,你想马上解封,你得有朋友。没有朋友,你就等个十天半个月!更新一下 帖子浏览人挺多的,有问题可以在评论里相互交流,下面是原文:先让我说一句脏话:傻x微信风控系统 终于特么的聊天…

android随手记

Linearlayout:   gravity:本元素中所有子元素的重力方向   layout_gravity:本元素对于父元素的重力方向 自定义权限:http://www.cnblogs.com/it-tomorrow/p/4115161.html 注意:1 .在被调用时就算是normal权限也需要在加入,不然会permission Deney,在…

Keras 最新《面向小数据集构建图像分类模型》

本文地址:http://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html 本文作者:Francois Chollet 按照官方的文章实现过程有一些坑,彻底理解代码细节实现,理解keras的api具体使用方法也有…

aws lambda使用_使用AWS Lambda安排Slack消息

aws lambda使用Migrating to serverless brings a lot of questions. How do you do some of the non-serverless tasks, such as a cronjob in a serverless application?迁移到无服务器带来了很多问题。 您如何执行一些非无服务器的任务,例如无服务器应用程序中的…

powershell连接数据库_PowerShell 连接SQL Server 数据库

PowerShell 通过ADO.NET连接SQL Server数据库,并执行SQL脚本。工作中整理的一小段脚本,后来没有用上,先记录在这里:建立数据库连接查询返回一个DataTatble对象执行一条SQL语句通过事物执行多条SQL语句## 建立数据库连接.#function…