理解python的with語句

2022-07-01 11:21:08 字數 2885 閱讀 3463

有一些任務, 可能事先需要設定, 事後做清理工作. 對於這種場景, python的with語句提供了一種非常方變的處理方式, 乙個很好的例子是檔案處理. 你需要獲取乙個檔案的控制代碼, 從檔案中讀取資料, 然後關閉檔案控制代碼. 如果不用with語句, **如下:

file = open("/tmp/

foo.txt")

data =file.read()

file.close()

這裡有兩個比較煩人的地方, 一是可能忘記關閉控制代碼, 而是檔案讀取資料時發生異常, 卻沒有進行任何處理(檔案讀取資料發生異常時, 後面的**將得不到執行, 因此獲取的檔案控制代碼不能正常關閉), 下面的**可以解決這個問題:

file = open("

/tmp/foo.txt")

try:

data =file.read()

finally

: file.close()

雖然這段**工作良好, 但是太冗長了, 這時候就是with出馬的時候了. 用with寫法, 除了擁有更優雅的語法, 還能夠處理異常. 下面是上面**的with寫法:

with open("

/tmp/foo.txt

") as file:

data = file.read()

它是怎麼工作的呢?

基本思想是with關鍵字後面的語句生成的物件必須實現兩個方法, __enter__()和__exit__()方法. with關鍵字後面的語句被求值後, 返回物件的__enter__()方法被呼叫, 這個方法的返回值被賦值為as關鍵字後面的變數. 當with語句後面的**全部執行完之後, 將呼叫前面返回物件的__exit__()物件. 下面這個例子可以說明with語句如何工作:

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. 執行with語句後面的**塊, 列印sample變數的值

4. __exit__()方法被執行

with語句真正強大之處在於它可以處理異常, 你應該已經注意到了sample類的__exit__()方法有三個引數, 分別是type, value和trace. 這三個引數在異常處理時非常有用, 我們來改一下**, 看看到底是怎麼工作的:

class

sample:

def__enter__

(self):

return

self

def__exit__

(self, type, value, trace):

print

"type:

", type

print

"value:

", value

print

"trace:

", trace

defdo_something(self):

bar = 1/0

return bar + 10

defget_sample():

return

sample()

with get_sample() as sample:

sample.do_something()

執行後的結果如下:

type: '

exceptions.zerodivisionerror

'>value: integer division or modulo by zero

trace:

object at 0xb749c11c>traceback (most recent call

last

): file

"a.python

", line 14, in

sample.do_something()

file

"a.python

", line 9, in

do_something

bar = 1/0

zerodivisionerror: integer division or modulo by zero

實際上, 在with語句後面的任何**丟擲異常時, __exit__()方法被執行, 即便不是因為sample類裡的方法產生的異常, 異常發生時, 與之關聯的type, value和trace也會傳給__exit__()方法. 因此丟擲的zerodivisionerror異常被列印出來了. 開發庫時, 清理資源, 關閉檔案等操作都可以放到__exit__()方法中.

因此, python的with語句可以讓**更簡練, 而且處理異常更加簡單.

原文參見

understanding python's "with" statement

Python中with語句的理解

with expr as var block 簡單說明 1,expr可以是任意表示式。2,as var是可選的。3,block是with語句的語句體1,計算expr,並獲取乙個上下文管理器。2,上下文管理器的exit 方法被儲存起來用於之後的呼叫。3,呼叫上下文管理器的enter 方法 4,如果wi...

python難理解的語句解析

1.移除字典點鍵值 key value 對 test dict 輸出原始的字典 print 字典移除前 str test dict 如果key zhihu 則輸出鍵值對字典 new dict 輸出移除後的字典 print 字典移除後 str new dict 字典移除前 字典移除後 2.合併字典 d...

python的語句 Python的語句

python中的兩種語句 1 if條件控制語句 格式 if a int input 請輸入第乙個數 b int input 請輸入第二個數 if a b print a比b小 if else a int input 請輸入第乙個數 b int input 請輸入第二個數 if a b print a...