理解Python中的With语句


Posted in Python onFebruary 02, 2015

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
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

行代码,输出如下

bash-3.2$ ./with_example01.py

In __enter__()

sample: Foo

In __exit__()

正如你看到的,

__enter__()方法被执行

__enter__()方法返回的值 - 这个例子中是"Foo",赋值给变量'sample'
执行代码块,打印变量"sample"的值为 "Foo"

__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()

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

代码执行后:

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_somet hing()

  File "./with_example02.py", line 15, in do_something

    bar = 1/0

ZeroDivisionError: integer division or modulo by zero

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

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

示例代码可以在Github上面找到。

Python 相关文章推荐
使用Python &amp; Flask 实现RESTful Web API的实例
Sep 19 Python
Python使用getpass库读取密码的示例
Oct 10 Python
简单实现python画圆功能
Jan 25 Python
python实现微信远程控制电脑
Feb 22 Python
把csv文件转化为数组及数组的切片方法
Jul 04 Python
tensorflow使用神经网络实现mnist分类
Sep 08 Python
学习python可以干什么
Feb 26 Python
Python符号计算之实现函数极限的方法
Jul 15 Python
Django上使用数据可视化利器Bokeh解析
Jul 31 Python
Python学习笔记之lambda表达式用法详解
Aug 08 Python
Python中Cookies导出某站用户数据的方法
May 17 Python
Python多线程实用方法以及共享变量资源竞争问题
Apr 12 Python
Linux环境下MySQL-python安装过程分享
Feb 02 #Python
Python中用pycurl监控http响应时间脚本分享
Feb 02 #Python
Python列表(list)常用操作方法小结
Feb 02 #Python
Python Sleep休眠函数使用简单实例
Feb 02 #Python
Python中实现从目录中过滤出指定文件类型的文件
Feb 02 #Python
Python实现二分法算法实例
Feb 02 #Python
Python标准异常和异常处理详解
Feb 02 #Python
You might like
java EJB 加密与解密原理的一个例子
2008/01/11 PHP
PHP跨时区(UTC时间)应用解决方案
2013/01/11 PHP
Yii数据模型中rules类验证器用法分析
2016/07/15 PHP
IE6,IE7下js动态加载图片不显示错误
2010/07/17 Javascript
jQuery bind事件使用详解
2011/05/05 Javascript
JavaScript/jQuery 表单美化插件小结
2012/02/14 Javascript
setInterval与clearInterval的使用示例代码
2014/01/28 Javascript
javascript常用的正则表达式实例
2014/05/15 Javascript
Javascript中arguments用法实例分析
2015/06/13 Javascript
jQuery实现仿微软首页感应鼠标变化滑动窗口效果
2015/10/08 Javascript
javascript创建对象的几种模式介绍
2016/05/06 Javascript
jQuery悬停文字提示框插件jquery.tooltipster.js用法示例【附demo源码下载】
2016/07/19 Javascript
form+iframe解决跨域上传文件的方法
2016/11/18 Javascript
PHP获取当前页面完整URL的方法
2016/12/02 Javascript
JavaScript html5利用FileReader实现上传功能
2020/03/27 Javascript
简述vue路由打开一个新的窗口的方法
2018/11/29 Javascript
node.js ws模块搭建websocket服务端的方法示例
2019/04/25 Javascript
JQuery表单元素取值赋值方法总结
2020/05/12 jQuery
vue 里面的 $forceUpdate() 强制实例重新渲染操作
2020/09/21 Javascript
nuxt静态部署打包相对路径操作
2020/11/06 Javascript
Python爬豆瓣电影实例
2018/02/23 Python
使用pandas模块读取csv文件和excel表格,并用matplotlib画图的方法
2018/06/22 Python
Python学习之路之pycharm的第一个项目搭建过程
2020/06/18 Python
利用SVG和CSS3来实现一个炫酷的边框动画
2015/07/22 HTML / CSS
html5 datalist标签使用示例(自动完成组件)
2014/05/04 HTML / CSS
澳大利亚儿童和婴儿产品在线商店:Lime Tree Kids
2017/10/05 全球购物
意大利简约的休闲品牌:Aspesi
2018/02/08 全球购物
Simons官方网站:加拿大时尚零售商
2020/02/20 全球购物
酒店办公室文员岗位职责
2013/12/18 职场文书
大学生关于奋斗的演讲稿
2014/01/09 职场文书
主管会计岗位职责
2014/03/13 职场文书
白酒营销策划方案
2014/08/17 职场文书
暑期学习心得体会
2014/09/02 职场文书
领导干部遵守党的政治纪律情况思想汇报
2014/09/14 职场文书
行政助理岗位职责范本
2015/04/11 职场文书
2015年公司国庆放假通知
2015/07/30 职场文书