理解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 相关文章推荐
12步入门Python中的decorator装饰器使用方法
Jun 20 Python
Python实现Sqlite将字段当做索引进行查询的方法
Jul 21 Python
Python实现好友全头像的拼接实例(推荐)
Jun 24 Python
Python:Scrapy框架中Item Pipeline组件使用详解
Dec 27 Python
python 简单照相机调用系统摄像头实现方法 pygame
Aug 03 Python
Python实现繁体中文与简体中文相互转换的方法示例
Dec 18 Python
Python的UTC时间转换讲解
Feb 26 Python
Python3.5面向对象与继承图文实例详解
Apr 24 Python
python 实现生成均匀分布的点
Dec 05 Python
Python如何把字典写入到CSV文件的方法示例
Aug 23 Python
关于多种方式完美解决Python pip命令下载第三方库的问题
Dec 21 Python
python3.9和pycharm的安装教程并创建简单项目的步骤
Feb 03 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函数篇之掌握ord()与chr()函数应用
2011/12/05 PHP
解析strtr函数的效率问题
2013/06/26 PHP
php简单日历函数
2015/10/28 PHP
php + WebUploader实现图片批量上传功能
2019/05/06 PHP
javascript 类方法定义还是有点区别
2009/04/15 Javascript
用jquery等比例控制图片宽高的具体实现
2014/01/28 Javascript
jQuery中addClass()方法用法实例
2015/01/05 Javascript
使用 TypeScript 重新编写的 JavaScript 坦克大战游戏代码
2015/04/07 Javascript
javascript基本算法汇总
2016/03/09 Javascript
JS控制静态页面传递参数并获取参数应用
2016/08/10 Javascript
利用Jasmine对Angular进行单元测试的方法详解
2017/06/12 Javascript
使用FileReader API创建Vue文件阅读器组件
2018/04/03 Javascript
在vue中高德地图引入和轨迹的绘制的实现
2019/10/11 Javascript
解决windows下Sublime Text 2 运行 PyQt 不显示的方法分享
2014/06/18 Python
Python functools模块学习总结
2015/05/09 Python
python实现搜索本地文件信息写入文件的方法
2016/02/22 Python
Python实现判断给定列表是否有重复元素的方法
2018/04/11 Python
对Python3中的input函数详解
2018/04/22 Python
python使用tornado实现简单爬虫
2018/07/28 Python
Django获取该数据的上一条和下一条方法
2019/08/12 Python
python 并发编程 非阻塞IO模型原理解析
2019/08/20 Python
使用OpenCV实现仿射变换—平移功能
2019/08/29 Python
使用Python给头像戴上圣诞帽的图像操作过程解析
2019/09/20 Python
实现CSS3中的border-radius(边框圆角)示例代码
2013/07/19 HTML / CSS
Html5实现iPhone开机界面示例代码
2013/06/30 HTML / CSS
Noon埃及:埃及在线购物
2019/11/26 全球购物
.NET里面什么时候需要调用垃圾回收
2015/06/01 面试题
个人生活学习自我评价范文
2013/11/26 职场文书
四风对照检查剖析材料
2014/10/07 职场文书
四年级小学生评语
2014/12/26 职场文书
煤矿安全保证书
2015/02/27 职场文书
2015年法制宣传月活动总结
2015/03/26 职场文书
全国助残日活动总结
2015/05/11 职场文书
婚宴领导致辞
2015/07/28 职场文书
幼儿园科学课教学反思
2016/03/03 职场文书
吃通javascript正则表达式
2021/04/21 Javascript