Python tricks(4) -- with statement
简介
with是从2.5版本引入的一个语法. 这个语法本身是为了解决try..finally繁琐的释放各类资源(文件句柄, Lock等)的问题.
如果想在旧版本中使用这个功能, 直接引入future模块就可以.
1 |
from
__future__ import
with_statement |
举例简单说明一下没有with和有with的代码区别
1
2
3
4
5
6 |
try : dict_file =
open ( "dict_file_path" ) for
line in
dict_file: print
line, # do something finally : dict_file.close() |
用with-statement的方式如下
1
2
3 |
with open ( "dict_file_path" ) as dict_file: for
line in
dict_file: print
line, # do something |
明显使用了with之后语法更加简洁.
官方对于with-statement的定义如下
1
2 |
with_stmt :: =
"with"
with_item ( ","
with_item) *
":"
suite with_item :: =
expression [ "as"
target] |
从定义中, 我们可以看出, 如果想通过with使用多个资源的话, 可以使用下面的写法
1 |
with open ( "d1_file" ) as d1, open ( "d2_file" ) as d2: |
as部分是可有可无的, 对于lock等这类资源来说一般都是这种用法
个人认为, with-statement是现在带有内存管理语言的折中处理方法, 对于c++来说, 可以使用RAII的方式, 一个类有明确的析构函数, 在超出作用域之后会被调用, 在析构函数内进行资源的释放是非常不错的选择. 也体现了c++的高效, 灵活和优雅.
Java, python这类语言都无法做到, 但是语言自身的异常机制都非常完善, 不像c++为了兼容c导致异常机制显得有点鸡肋. try..catch..finally就成为了这类语言用来进行资源释放的方式, GC(垃圾回收)回收内存的时间不确定, 无法利用RAII.
With-statement Magic Method
python语言层面上对于with的支持是通过magic method来实现的, 和一般的python特性一样.
使用PEP343中with-statement的定义来引入这两个magic method
1
2 |
with VAR =
EXPR: BLOCK |
直接翻译过来就是
1
2
3
4
5
6 |
VAR =
EXPR VAR.__enter__() try : BLOCK finally : VAR.__exit__() |
我们可以清楚的看到这两个magic method分别是__enter__和__exit__, 一个在进入with-statement block的时候初始化, 一个在离开的时候进行cleanup工作.
下面来举一个简单的timer例子.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 |
import
time class
Timer( object ): def
__init__( self ): pass def
__enter__( self ): self .start =
time.time() def
__exit__( self , exception_type, exception_val, trace): print
"elapsed:" , time.time() -
self .start if
__name__ = =
"__main__" : with Timer(): [i for
i in
xrange ( 10000000 )] |
运行结果如下:
1 |
elapsed: 1.32907581329 |
timer是一个简单实用的类, 在编写性能测试代码的时候, 经常会用到.
水平有限, 欢迎拍砖!
参考文献:
- PEP343: http://www.python.org/dev/peps/pep-0343/
- Python Docs <Compound statements>: http://docs.python.org/2/reference/compound_stmts.html#the-with-statement
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。