理解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 相关文章推荐
easy_install python包安装管理工具介绍
Feb 10 Python
python类参数self使用示例
Feb 17 Python
Python中的元类编程入门指引
Apr 15 Python
浅谈Python单向链表的实现
Dec 24 Python
python中numpy基础学习及进行数组和矢量计算
Feb 12 Python
python方向键控制上下左右代码
Jan 20 Python
Python统计单词出现的次数
Apr 04 Python
Python语言快速上手学习方法
Dec 14 Python
Python利用itchat库向好友或者公众号发消息的实例
Feb 21 Python
python实现感知机线性分类模型示例代码
Jun 02 Python
python解释器spython使用及原理解析
Aug 24 Python
详解Pycharm与anaconda安装配置指南
Aug 25 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
如何做到多笔资料的同步
2006/10/09 PHP
深入PHP内存相关的功能特性详解
2013/06/08 PHP
php中$_GET与$_POST过滤sql注入的方法
2014/11/03 PHP
详解PHP swoole process的使用方法
2017/08/26 PHP
PDO::inTransaction讲解
2019/01/28 PHP
javascript-TreeView父子联动效果保持节点状态一致
2007/08/12 Javascript
JavaScript 继承详解(四)
2009/07/13 Javascript
Javascript 学习笔记 错误处理
2009/07/30 Javascript
js正文内容高亮效果的实现方法
2013/06/30 Javascript
JavaScript等比例缩放图片控制超出范围的图片
2013/08/06 Javascript
JS获取屏幕,浏览器窗口大小,网页高度宽度(实现代码)
2013/12/17 Javascript
javascript父、子页面交互技巧总结
2014/08/08 Javascript
jQuery的文档处理程序详解
2016/05/10 Javascript
AngularJS基础 ng-submit 指令简单示例
2016/08/03 Javascript
关于JS中二维数组的声明方法
2016/09/24 Javascript
网络传输协议(http协议)
2016/11/18 Javascript
详解nodejs中的process进程
2017/03/19 NodeJs
使用JS编写的随机抽取号码的小程序
2017/08/11 Javascript
浅析vue-router jquery和params传参(接收参数)$router $route的区别
2018/08/03 jQuery
vue-cli 使用vue-bus来全局控制的实例讲解
2018/09/15 Javascript
CKEditor4配置与开发详细中文说明文档
2018/10/08 Javascript
VSCode 配置uni-app的方法
2020/07/11 Javascript
解决VUE mounted 钩子函数执行时 img 未加载导致页面布局的问题
2020/07/27 Javascript
js实现盒子移动动画效果
2020/08/09 Javascript
基于Python实现下载网易音乐代码实例
2020/08/10 Python
浅谈Python xlwings 读取Excel文件的正确姿势
2021/02/26 Python
AmazeUI底部导航栏与分享按钮的示例代码
2020/08/18 HTML / CSS
英国香水店:The Perfume Shop
2017/03/27 全球购物
苹果音乐订阅:Apple Music
2018/08/02 全球购物
英国领先的游戏零售商:GAME
2019/09/24 全球购物
英国排名第一的餐具品牌:Denby Pottery
2019/11/01 全球购物
公司周年庆典策划方案
2014/05/17 职场文书
岗位职责范本大全
2015/02/26 职场文书
公司老总年会致辞
2015/07/30 职场文书
python编写函数注意事项总结
2021/03/29 Python
Python制作春联的示例代码
2022/01/22 Python