理解Python中的With语句


Posted in Python onMarch 18, 2016

 有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。 Without the with statement, one would write something along the lines of: 如果不用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__()方法。 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

运行代码,输出如下

bash-3.2$ ./with_example01.py
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
 
 
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后面的语句所返回的对象有__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

 实际上,在with后面的代码块抛出任何异常时,__exit__()方法被执行。正如例子所示,异常抛出时,与之关联的type,value和stack trace传给__exit__()方法,因此抛出的ZeroDivisionError异常被打印出来了。

开发库时,清理资源,关闭文件等等操作,都可以放在__exit__方法当中。

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

以上就是关于Python中的With语句的理解,希望对大家的学习有所帮助。

Python 相关文章推荐
Python如何实现MySQL实例初始化详解
Nov 06 Python
详解django三种文件下载方式
Apr 06 Python
彻彻底底地理解Python中的编码问题
Oct 15 Python
python 返回列表中某个值的索引方法
Nov 07 Python
Django中使用Celery的方法示例
Nov 29 Python
python 通过可变参数计算n个数的乘积方法
Jun 13 Python
Python的matplotlib绘图如何修改背景颜色的实现
Jul 16 Python
python脚本执行CMD命令并返回结果的例子
Aug 14 Python
Python利用 utf-8-sig 编码格式解决写入 csv 文件乱码问题
Feb 21 Python
Python图像处理库PIL的ImageDraw模块介绍详解
Feb 26 Python
基于Python第三方插件实现西游记章节标注汉语拼音的方法
May 22 Python
python从PDF中提取数据的示例
Oct 30 Python
简述Python中的进程、线程、协程
Mar 18 #Python
Python实现计算最小编辑距离
Mar 17 #Python
Python引用模块和查找模块路径
Mar 17 #Python
Python使用tablib生成excel文件的简单实现方法
Mar 16 #Python
Python保存MongoDB上的文件到本地的方法
Mar 16 #Python
Python3中的真除和Floor除法用法分析
Mar 16 #Python
学习python类方法与对象方法
Mar 15 #Python
You might like
php 调用远程url的六种方法小结
2009/11/02 PHP
PHP列出MySQL中所有数据库的方法
2015/03/12 PHP
PHP引用的调用方法分析
2016/04/25 PHP
手把手编写PHP框架 深入了解MVC运行流程
2016/09/19 PHP
php通过pecl方式安装扩展的实例讲解
2018/02/02 PHP
laravel执行php artisan migrate报错的解决方法
2019/10/09 PHP
实例化php类时传参的方法分析
2020/06/05 PHP
jquery文本框中的事件应用以输入邮箱为例
2014/05/06 Javascript
使用GruntJS构建Web程序之合并压缩篇
2014/06/06 Javascript
js创建表单元素并使用submit进行提交
2014/08/14 Javascript
jqGrid 学习笔记整理——进阶篇(一 )
2016/04/17 Javascript
JavaScript预解析及相关技巧分析
2016/04/21 Javascript
点击页面任何位置隐藏div的实现方法
2016/09/05 Javascript
jQuery动态增减行的实例代码解析(推荐)
2016/12/05 Javascript
详解Javascript中DOM的范围
2017/02/13 Javascript
微信小程序 action-sheet 反馈上拉菜单简单实例
2017/05/11 Javascript
Javascript实现倒计时时差效果
2017/05/18 Javascript
JS中type=&quot;button&quot;和type=&quot;submit&quot;的区别
2017/07/04 Javascript
详解react-native-fs插件的使用以及遇到的坑
2017/09/12 Javascript
nodejs使用http模块发送get与post请求的方法示例
2018/01/08 NodeJs
jQuery实现的点击按钮改变样式功能示例
2018/07/21 jQuery
详解Vue 全局变量,局部变量
2019/04/17 Javascript
JS中的算法与数据结构之字典(Dictionary)实例详解
2019/08/20 Javascript
通过实例解析json与jsonp原理及使用方法
2020/09/27 Javascript
在Python3中使用asyncio库进行快速数据抓取的教程
2015/04/02 Python
django-rest-framework 自定义swagger过程详解
2019/07/18 Python
Python 动态导入对象,importlib.import_module()的使用方法
2019/08/28 Python
python实现网页录音效果
2020/10/26 Python
定制iPhone和Macbook保护壳:Slick Case
2018/11/21 全球购物
大学生护理专业自荐信
2013/10/03 职场文书
高等教育学自荐书范文
2014/02/10 职场文书
cf收人广告词大全
2014/03/14 职场文书
企业授权委托书范本
2014/04/02 职场文书
酒店节能减排方案
2014/05/26 职场文书
倡议书作文
2015/01/19 职场文书
Python快速实现一键抠图功能的全过程
2021/06/29 Python