Python with...as... 語法深入解析

pythontab發表於2016-11-23

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。這些引數在異常處理中相當有用。


相關文章