理解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二叉树的实现实例
Nov 21 Python
Python 异常处理实例详解
Mar 12 Python
Python语言实现百度语音识别API的使用实例
Dec 13 Python
python如何使用unittest测试接口
Apr 04 Python
python3实现SMTP发送邮件详细教程
Jun 19 Python
python opencv 读取本地视频文件 修改ffmpeg的方法
Jan 26 Python
Python学习笔记之自定义函数用法详解
Jun 08 Python
Python高级特性——详解多维数组切片(Slice)
Nov 26 Python
Matplotlib绘制雷达图和三维图的示例代码
Jan 07 Python
10张动图学会python循环与递归问题
Feb 06 Python
Pytorch反向传播中的细节-计算梯度时的默认累加操作
Jun 05 Python
Python正则表达式中flags参数的实例详解
Apr 01 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
javascript cookies 设置、读取、删除实例代码
2010/04/12 Javascript
JSON 和 JavaScript eval使用说明
2010/06/13 Javascript
JQuery从头学起第一讲
2010/07/04 Javascript
jquery关于图形报表的运用实现代码
2011/01/06 Javascript
jcrop基本参数一览
2013/07/16 Javascript
基于jquery编写的横向自适应幻灯片切换特效的实例代码
2013/08/06 Javascript
从jquery的过滤器.filter()方法想到的
2013/09/29 Javascript
php跨域调用json的例子
2013/11/13 Javascript
JavaScript Math.ceil 方法(对数值向上取整)
2015/01/09 Javascript
Js与Jq 获取页面元素值的方法和差异对比
2015/04/30 Javascript
javascript文件加载管理简单实现方法
2015/07/25 Javascript
jQuery+css实现的时钟效果(兼容各浏览器)
2016/01/27 Javascript
jquery zTree异步加载简单实例讲解
2016/02/25 Javascript
jQuery Mobile页面返回不需要重新get
2016/04/26 Javascript
基于jQuery的select下拉框选择触发事件实例分析
2016/11/18 Javascript
JS回调函数基本定义与用法实例分析
2017/05/24 Javascript
layer弹出子iframe层父子页面传值的实现方法
2018/11/22 Javascript
javascript中join方法实例讲解
2019/02/21 Javascript
layui实现checkbox的目录树tree的例子
2019/09/12 Javascript
electron 安装,调试,打包的具体使用
2019/11/06 Javascript
[05:34]2014DOTA2国际邀请赛中国区预选赛精彩TOPPLAY第二弹
2014/06/25 DOTA
[00:37]2016完美“圣”典风云人物:rOtk宣传片
2016/12/09 DOTA
Python实现中一次读取多个值的方法
2018/04/22 Python
Python画柱状统计图操作示例【基于matplotlib库】
2018/07/04 Python
HTML如何让IMG自动适应DIV容器大小的实现方法
2020/02/25 HTML / CSS
美国领先的男士和女士内衣购物网站:Freshpair
2019/02/25 全球购物
西安众合通用.net笔试题
2013/03/18 面试题
自我鉴定三原则
2014/01/13 职场文书
七年级英语教学反思
2014/01/15 职场文书
海飞丝的广告词
2014/03/20 职场文书
祖国在我心中演讲稿300字
2014/05/04 职场文书
自查自纠工作总结
2014/10/15 职场文书
市贸粮局召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
送给客户微信问候语!
2019/07/04 职场文书
创业计划书之旅游网站
2019/09/06 职场文书
python实现简易自习室座位预约系统
2021/06/30 Python