python的with语句,超级强大
With语句是什么?
有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。
如果不用with语句,代码如下:
1
2
3
|
file = open ( "/tmp/foo.txt" ) data = file .read() file .close() |
这里有两个问题。一是可能忘记关闭文件句柄;二是文件读取数据发生异常,没有进行任何处理。下面是处理异常的加强版本:
1
2
3
4
5
|
file = open ( "/tmp/foo.txt" ) try : data = file .read() finally : file .close() |
虽然这段代码运行良好,但是太冗长了。这时候就是with一展身手的时候了。除了有更优雅的语法,with还可以很好的处理上下文环境产生的异常。下面是with版本的代码:
1
2
|
with open ( "/tmp/foo.txt" ) file : data = file .read() |
with如何工作?
这看起来充满魔法,但不仅仅是魔法,Python对with的处理还很聪明。基本思想是with所求值的对象必须有一个__enter__()方法,一个__exit__()方法。
紧跟with后面的语句被求值后,返回对象的__enter__()方法被调用,这个方法的返回值将被赋值给as后面的变量。当with后面的代码块全部被执行完之后,将调用前面返回对象的__exit__()方法。
下面例子可以具体说明with如何工作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#!/usr/bin/env # 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 print "sample:" , |
运行代码,输出如下
1
2
3
4
|
bash - 3.2 $ / with_example01.py In sample: In |
正如你看到的,
1. __enter__()方法被执行
2. __enter__()方法返回的值 - 这个例子中是"Foo",赋值给变量'sample'
3. 执行代码块,打印变量"sample"的值为 "Foo"
4. __exit__()方法被调用
with真正强大之处是它可以处理异常。可能你已经注意到Sample类的__exit__方法有三个参数- val, type 和 trace。 这些参数在异常处理中相当有用。我们来改一下代码,看看具体如何工作的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#!/usr/bin/env # class Sample: def __enter__( self ): return self def __exit__( self , type , print "type:" , type print "value:" , print "trace:" , def do_something( self ): bar = 1 / 0 return bar + 10 with sample.do_something() |
这个例子中,with后面的get_sample()变成了Sample()。这没有任何关系,只要紧跟with后面的语句所返回的对象有__enter__()和__exit__()方法即可。此例中,Sample()的__enter__()方法返回新创建的Sample对象,并赋值给变量sample。
代码执行后:
1
2
3
4
5
6
7
8
9
10
|
bash - 3.2 $ / with_example02.py type : type 'exceptions.ZeroDivisionError' > value: or modulo trace: object at 0x1004a8128 > Traceback File "./with_example02.py" , 19 , in <module> sample.do_something() File "./with_example02.py" , 15 , in do_something bar = 1 / 0 ZeroDivisionError: or modulo |
实际上,在with后面的代码块抛出任何异常时,__exit__()方法被执行。正如例子所示,异常抛出时,与之关联的type,value和stack trace传给__exit__()方法,因此抛出的ZeroDivisionError异常被打印出来了。开发库时,清理资源,关闭文件等等操作,都可以放在__exit__方法当中。
因此,Python的with语句是提供一个有效的机制,让代码更简练,同时在异常产生时,清理工作更简单。
示例代码可以在Github上面找到。
python的with语句,超级强大的更多相关文章
- 理解python的with语句
Python’s with statement provides a very convenient way of dealing with the situation where you have ...
- 转: 理解Python的With语句
Python’s with statement provides a very convenient way of dealing with the situation where you have ...
- python——异常except语句用法与引发异常
except: #捕获所有异常 except: <异常名>: #捕获指定异常 except:<异常名1,异常名2):捕获异常1或者异常2 except:<异常名>,< ...
- Python之with语句
Python之with语句 在Python中,我们在打开文件的时候,为了代码的健壮性,通常要考虑一些异常情况,比如: try: ccfile = open('/path/data') content ...
- (Python )控制流语句if、for、while
这一节,我们将学习Python的控制流语句,主要包括if.for.while.break.continue 和pass语句 1. If语句 if语句也许是我们最熟悉的语句.其使用方法如下: x=inp ...
- Python的with语句
写过多线程程序的人肯定对各种锁很熟悉,尤其是下面这种代码 def lock_usage: lock.Lock() if(...) : lock.Unlock() return lock.Unlock( ...
- Python学习教程(learning Python)--3.3.4 Python的if-elif-else语句
Python的if-elif-else语句用于多种条件判断后选择某个语句块执行.该语句可以利用一系列条件表达式进行检查,并在某个表达式为真的情况下执行相应的代码.需要注意的是,虽然if/elif/el ...
- 简单探讨python中的语句和语法
python程序结构 python"一切皆对象",这是接触python听到最多的总结了.在python中最基层的单位应该就是对象了,对象需要靠表达式建立处理,而表达式往往存在于语句 ...
- python assert 断言语句的作用
python assert 断言语句的作用 assert语句的应用场景 使用assert语句是一个很好的习惯. 我们在编写代码的时候, 不知道程序会在什么时候崩溃, 与其让它在深度运行时崩溃, 不如预 ...
随机推荐
- ECJTUACM16 Winter vacation training #4 题解&源码
A......................................................................................... 题目链接→Code ...
- bzoj3238--后缀自动机
显然只需求LCP(i,j)就可以了. 将s反转,然后插入后缀自动机.由于后缀自动机的link指针构成了一棵后缀树,而字符串又反转过,所以两个结点的LCP就是LCA. 树形DP,求出以每个结点为LCA的 ...
- iOS程序生命周期 AppDelegate
iOS的应用程序的生命周期,还有程序是运行在前台还是后台,应用程序各个状态的变换,这些对于开发者来说都是很重要的. iOS系统的资源是有限的,应用程序在前台和在后台的状态是不一样的.在后台时,程序会受 ...
- java 双击jar包操作
如何使jar包直接双击运行? 测试:MyMenu.java 类名:MyMenu 写完java代码后,发现物理路径下为: 当我按住Shift键,在此处游记,打开命令行窗口: 执行命令:javac My ...
- iOS动画案例(2) 仿网易新闻标题动画
由于产品的需要,做了一个和网易新闻标题类似的动画效果,现在新闻类的APP都是采用这样的动画效果,来显示更多的内容.先看一下动画效果: 由于这个动画效果在很多场合都有应用,所以我专门封装了一个控 ...
- DLL 导出函数
DLL的链接方式分为两种:隐式链接和显式链接 DLL导出的函数 和 导出类在调用时,有些区别,这里暂时不讲,直说简单的导出函数: 隐式链接: #include "stdafx.h" ...
- 不惧面试:HTTP协议(3) - Cookie
v博客前言 先交代下背景,写这个系列的原因是总结自己遇到的面试题以及可能遇到的题目,更重要的是,今年定的目标是掌握网络这一块的知识点,先是搞懂HTTP协议,然后是TCP/IP协议,再就是WCF如何运用 ...
- 开源OSS.Social微信项目进阶介绍
在开源OSS.Social微信项目解析的随笔中,我简单给大家分享了进行中微信项目的概要设计,主要在讲述解决思路和过程,没有详细实现和使用介绍.本着不能马虎的态度,这篇文章我来给大家分解一下项目结构,使 ...
- PostgreSQL指南
PostgreSQL指南 历史简介 最近几年Postgres的关注度变得越来越高. 它加快了Postgres的发展步伐, 与此同时其他 的关系数据库系统的发展放缓. 在数据库领域中 Postgre S ...
- Asp.net mvc 知多少(九)
本系列主要翻译自<ASP.NET MVC Interview Questions and Answers >- By Shailendra Chauhan,想看英文原版的可访问http:/ ...