With陳述句是什么? 有一些任務,可能事先需要設定,事后做清理作業,對于這種場景,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如何作業?
這看起來充滿魔法,但不僅僅是魔法,Python對with的處理還很聰明,基本思想是with所求值的物件必須有一個__enter__()方法,一個__exit__()方法, 緊跟with后面的陳述句被求值后,回傳物件的__enter__()方法被呼叫,這個方法的回傳值將被賦值給as后面的變數,當with后面的代碼塊全部被執行完之后,將呼叫前面回傳物件的__exit__()方法, 下面例子可以具體說明with如何作業:
#!/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, 這些引數在例外處理中相當有用,我們來改一下代碼,看看具體如何作業的
#!/usr/bin/env python # with_example02.py class Sample: def __enter__(self): return self def __exit__(self, type, value, trace): print "type:", type print "value:", value print "trace:", trace def do_something(self): bar = 1/0 return bar + 10 with Sample() as sample: sample.do_something()
這個例子中,with后面的get_sample()變成了Sample(),這沒有任何關系,只要緊跟with后面的陳述句所回傳的物件有__enter__()和__exit__()方法即可,此例中,Sample()的__enter__()方法回傳新創建的Sample物件,并賦值給變數sample, 代碼執行后:
bash-3.2$ ./with_example02.py type: <type 'exceptions.ZeroDivisionError'> value: integer division or modulo by zero trace: <traceback object at 0x1004a8128> Traceback (most recent call last): File "./with_example02.py", line 19, in <module> sample.do_something() File "./with_example02.py", line 15, in do_something bar = 1/0 ZeroDivisionError: integer division or modulo by zero
實際上,在with后面的代碼塊拋出任何例外時,__exit__()方法被執行,正如例子所示,例外拋出時,與之關聯的type,value和stack trace傳給__exit__()方法,因此拋出的ZeroDivisionError例外被列印出來了,開發庫時,清理資源,關閉檔案等等操作,都可以放在__exit__方法當中, 因此,Python的with陳述句是提供一個有效的機制,讓代碼更簡練,同時在例外產生時,清理作業更簡單,
原文鏈接:https://www.cnblogs.com/DswCnblog/p/6126588.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/499029.html
標籤:Python
下一篇:字串(str、bytes)
