Python tricks(4) -- with statement
简介
with是从2.5版本引入的一个语法. 这个语法本身是为了解决try..finally繁琐的释放各类资源(文件句柄, Lock等)的问题.
如果想在旧版本中使用这个功能, 直接引入future模块就可以.
from __future__ import with_statement
举例简单说明一下没有with和有with的代码区别
try:
dict_file = open("dict_file_path")
for line in dict_file:
print line, # do something
finally:
dict_file.close()
用with-statement的方式如下
with open("dict_file_path") as dict_file:
for line in dict_file:
print line, # do something
明显使用了with之后语法更加简洁.
官方对于with-statement的定义如下
with_stmt ::= "with" with_item ("," with_item)* ":" suite
with_item ::= expression ["as" target]
从定义中, 我们可以看出, 如果想通过with使用多个资源的话, 可以使用下面的写法
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
with VAR = EXPR:
BLOCK
直接翻译过来就是
VAR = EXPR
VAR.__enter__()
try:
BLOCK
finally:
VAR.__exit__()
我们可以清楚的看到这两个magic method分别是__enter__和__exit__, 一个在进入with-statement block的时候初始化, 一个在离开的时候进行cleanup工作.
下面来举一个简单的timer例子.
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)]
运行结果如下:
elapsed: 1.32907581329
timer是一个简单实用的类, 在编写性能测试代码的时候, 经常会用到.
水平有限, 欢迎拍砖!
2014.4.19 添加一个with带有异常处理的demo
以一个操作数据库的session为例, 下面的方式可以替代繁琐的try...except...finally语句, 可以包装sqlalchemy的session.
笔者用这个简单的封装作为sqlalchemy来方便处理session相关的操作. commit操作需要自己去调用, 也可以加入到exit方法中.
class Wrapper(object):
'''A context manager to automatically close an object with a close method
in a with statement.''' def __init__(self, obj):
self.obj = obj def __enter__(self):
return self.obj # bound to target def __exit__(self, exception_type, exception_val, trace):
if exception_type:
try:
self.obj.rollback()
except AttributeError: # obj cannot rollback
return True # exception handled successfully
try:
self.obj.close()
except AttributeError: # obj isn't closable
return True # exception handled successfully
参考文献:
- 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
Python tricks(4) -- with statement的更多相关文章
- Python Tricks 若干
赵斌 - APRIL 29, 2015 在 python 代码中可以看到一些常见的 trick,在这里做一个简单的小结. json 字符串格式化 在开发 web 应用的时候经常会用到 json 字符串 ...
- python tricks
1. cities = ['Marseille', 'Amsterdam', 'New York', 'Londom'] # the good way for i, city in enumerate ...
- Python tricks(7) -- new-style class的__slots__属性
__slots__是在python 2.2开始引入的一个新特性, 我们来看一下官方给出的解释. This class variable can be assigned a string, iterab ...
- Python tricks(6) -- python代码执行的效率
python作为一个动态语言, 本身学习曲线比较平滑, 效率相比起来会比c++和java低一些. 脚本语言都是运行时编译的, 这个对于效率的影响是非常大的. 我借用参考1的代码, 加了点代码impor ...
- Python tricks(5) -- string和integer的comparison操作
我们都知道, python是一个强类型的语言, 也是一个动态类型的语言. 但是在python2.X系列中, 这个强类型是需要打折扣的, 是非常接近强类型. 我们来看下面的代码片段 In [1]: 'a ...
- Python tricks(3) -- list和dict的遍历和方法
每个人在使用python的过程中都会遍历list和dict. List遍历 最常用最简单的遍历list的方法 a = ["a", "b", "c&qu ...
- Python tricks(2) -- method默认参数和闭包closure
Python的method可以设置默认参数, 默认参数如果是可变的类型, 比如list, map等, 将会影响所有的该方法调用. 下面是一个简单的例子 def f(a=None, l=[]): if ...
- Python tricks(1) -- 动态定义一个新变量
python是动态语言, 无需声明变量即可使用. 传递一个tuple, list或者dict等等方式, 有时候这种方式的使用不是很好. 对于tuple和list来说都是用下标的访问方式(即使用[]), ...
- Some Python Tricks
python 的包管理很不好用,理解费力,故偷懒,模块仍按文件布局,写一个合并脚本将各个模块合并输出到一个脚本文件,分别管理,合并输出,回避了加载模块的问题 f-format 仅在python 3.6 ...
随机推荐
- 关于C#泛型作用的简单说明
泛型:即通过参数化类型来实现在同一份代码上操作多种数据类型.泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用. C#泛型的作用概述 C#泛型赋予了代码更强的类型安全,更 ...
- [图书] C++
作者 书名 Bjarne Stroustrup The Design and Evolution of C++Stanley B. Lippman C++ PrimerStanley B. ...
- DBCP连接池配置(DBCPUtils.java)
配置文件 db_dbcp.properites driverClass=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/db?useSSL= ...
- TFS二次开发11——标签(Label)
下图是在VS2010里创建Label的界面 可以看出创建Label 需要如下参数:Name.Comment.Path.Version .下面是代码实现: using Microsoft.TeamFou ...
- python----并发之协程
<python并发之协程>一: 单线程下实现并发,即只在一个主线程,并且cpu只有一个的情况下实现并发.(并发的本质:切换+保存状态) cpu正在运行一个任务,会在两种情况下切去执行其他的 ...
- POJ-1322 Chocolate(概率DP)
Chocolate Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9279 Accepted: 2417 Special Jud ...
- HDU-1394 Minimum Inversion Number(线段树求逆序数)
Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Ot ...
- 《机器学习实战》2.2.2分析数据:使用matplotlib创建散点图
#输出散点图 def f(): datingDataMat,datingLabels = file2matrix("datingTestSet3.txt") fig = plt.f ...
- POJ_1050_To the Max
To the Max Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 49811 Accepted: 26400 Desc ...
- Python:正则表达式概念
#正则表达式内容非常多,网上的学习资源也是目不暇接,我从中筛选学习并且整理出以下 的学习笔记 一.正则表达式匹配过程: 1.依次拿出表达式和文本中的字符比较 2.如果每一个字符都能匹配,则匹配成功:一 ...