理解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基础教程之popen函数操作其它程序的输入和输出示例
Feb 10 Python
Python多线程编程(五):死锁的形成
Apr 05 Python
Python基础语言学习笔记总结(精华)
Nov 14 Python
Tensorflow 利用tf.contrib.learn建立输入函数的方法
Feb 08 Python
解决Pandas to_json()中文乱码,转化为json数组的问题
May 10 Python
Python查看微信撤回消息代码
Jun 07 Python
Python之csv文件从MySQL数据库导入导出的方法
Jun 21 Python
10 行Python 代码实现 AI 目标检测技术【推荐】
Jun 14 Python
Python如何基于rsa模块实现非对称加密与解密
Jan 03 Python
Python可以实现栈的结构吗
May 27 Python
PyCharm+Miniconda3安装配置教程详解
Feb 16 Python
Python+腾讯云服务器实现每日自动健康打卡
Dec 06 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
PHP字符编码问题之GB2312 VS UTF-8解决方法
2011/06/23 PHP
PHP MYSQL实现登陆和模糊查询两大功能
2016/02/05 PHP
js静态作用域的功能。
2006/12/25 Javascript
网页开发中的容易忽略的问题 javascript HTML中的table
2009/04/15 Javascript
读jQuery之十 事件模块概述
2011/06/27 Javascript
Javascript new Date().valueOf()的作用与时间戳由来详解
2013/04/24 Javascript
js操纵跨frame的三级联动select下拉选项实例介绍
2013/05/19 Javascript
js解决弹窗问题实现班级跳转DIV示例
2014/01/06 Javascript
jquery序列化表单以及回调函数的使用示例
2014/07/02 Javascript
jquery实现表格本地排序的方法
2015/03/11 Javascript
js日期范围初始化得到前一个月日期的方法
2015/05/05 Javascript
基于 Node.js 实现前后端分离
2016/04/23 Javascript
AngularJS ng-bind-html 指令详解及实例代码
2016/07/30 Javascript
javascript数字验证的实例代码(推荐)
2016/08/20 Javascript
AngularJS通过ng-route实现基本的路由功能实例详解
2016/12/13 Javascript
js实现密码强度检验
2017/01/15 Javascript
微信小程序 chooseImage选择图片或者拍照
2017/04/07 Javascript
jQuery初级教程之网站品牌列表效果
2017/08/02 jQuery
关于 angularJS的一些用法
2017/11/29 Javascript
解决vue打包css文件中背景图片的路径问题
2018/09/03 Javascript
es6基础学习之解构赋值
2018/12/10 Javascript
React 使用Hooks简化受控组件的状态绑定
2019/03/18 Javascript
nodejs读取图片返回给浏览器显示
2019/07/25 NodeJs
layui select 禁止点击的实现方法
2019/09/05 Javascript
利用Python获取赶集网招聘信息前篇
2016/04/18 Python
使用Python来开发微信功能
2018/06/13 Python
python3环境搭建过程(利用Anaconda+pycharm)完整版
2020/08/19 Python
用Python制作音乐海报
2021/01/26 Python
使用HTML5做个画图板的方法介绍
2013/05/03 HTML / CSS
基于canvas使用贝塞尔曲线平滑拟合折线段的方法
2018/01/10 HTML / CSS
美国亚马逊旗下时尚女装网店:SHOPBOP(支持中文)
2020/10/17 全球购物
土木工程专业大学毕业生求职信
2013/10/13 职场文书
四风问题民主生活会对照检查材料思想汇报
2014/09/27 职场文书
红旗渠导游词
2015/02/09 职场文书
导游词之西安骊山
2019/12/20 职场文书
JavaScript ES6的函数拓展
2022/01/18 Javascript