with從Python 2.5就有,需要from __future__ import with_statement。自python 2.6開始,成為預設關鍵字。
也就是說with是一個控制流語句,跟if/for/while/try之類的是一類的,with可以用來簡化try finally程式碼,看起來可以比try finally更清晰。
with EXPRESSION [ as VARIABLE] WITH-BLOCK
基本思想是with所求值的物件必須有一個__enter__()方法,一個__exit__()方法。
緊跟with後面的語句被求值後,返回物件的__enter__()方法被呼叫,這個方法的返回值將被賦值給as後面的變數。當with後面的程式碼塊全部被執行完之後,將呼叫前面返回物件的__exit__()方法。
with expresion as variable的執行過程是,首先執行__enter__函式,它的返回值會賦給as後面的variable,想讓它返回什麼就返回什麼,只要你知道怎麼處理就可以了,如果不寫as variable,返回值會被忽略。
然後,開始執行with-block中的語句,不論成功失敗(比如發生異常、錯誤,設定sys.exit()),在with-block執行完成後,會執行__exit__函式。
這樣的過程其實等價於:
try: 執行 __enter__的內容 執行 with_block. finally: 執行 __exit__內容
再看個例子
file = open("/tmp/foo.txt") try: data = file.read() finally: file.close()
使用with...as...的方式替換,修改後的程式碼是:
with open("/tmp/foo.txt") as file: data = file.read()
#!/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
執行結果為
In __enter__() sample: Foo In __exit__()
1. __enter__()方法被執行
2. __enter__()方法返回的值 - 這個例子中是"Foo",賦值給變數'sample'
3. 執行程式碼塊,列印變數"sample"的值為 "Foo"
4. __exit__()方法被呼叫with真正強大之處是它可以處理異常。可能你已經注意到Sample類的__exit__方法有三個引數- val, type 和 trace。這些引數在異常處理中相當有用。