簡介html
with是從2.5版本引入的一個語法. 這個語法自己是爲了解決try..finally繁瑣的釋放各種資源(文件句柄, Lock等)的問題.python
若是想在舊版本中使用這個功能, 直接引入future模塊就能夠.c++
from __future__ import with_statement
舉例簡單說明一下沒有with和有with的代碼區別sql
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以後語法更加簡潔.express
官方對於with-statement的定義以下session
with_stmt ::= "with" with_item ("," with_item)* ":" suite with_item ::= expression ["as" target]
從定義中, 咱們能夠看出, 若是想經過with使用多個資源的話, 能夠使用下面的寫法app
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
參考文獻: