with語句是什麼?
有一些任務,可能事先需要設定,事後做清理工作。對於這種場景,python的with語句提供了一種非常方便的處理方式。乙個很好的例子是檔案處理,你需要獲取乙個檔案控制代碼,從檔案中讀取資料,然後關閉檔案控制代碼。如果不用with語句,**如下:
file = open("/tmp/foo.txt")
data = file.read()
file.close()
這裡有兩個問題:
是可能忘記關閉檔案控制代碼;
是檔案讀取資料發生異常,沒有進行任何處理。
下面是處理異常的加強版本:
try:
f = open('***')
except:
print 'fail to open'
exit(-1)
try:
do something
except:
do something
finally:
f.close()
雖然這段**執行良好,但是太冗長了。
這時候就是with一展身手的時候了。除了有更優雅的語法,with還可以很好的處理上下文環境產生的異常。
下面是with版本的**:
with
open("/tmp/foo.txt") as
file:
data = file.read()
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__()"
defget_sample
():return sample()
with get_sample() as sample:
print
"sample:", sample
執行**,輸出如下
bash-3.2$ ./with_example01.py
in __enter__()
sample: foo
in __exit__()
正如你看到的:
enter()方法被執行
enter()方法返回的值 ,這個例子中是」foo」,賦值給變數』sample』 執行**塊,列印變數」sample」的值為 「foo」
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
defdo_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: 'exceptions.zerodivisionerror'>
value: integer division or modulo by
zero
trace: at
0x1004a8128>
traceback (most recent call last):
file "./with_example02.py", line
19, in
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方法當中。
另外,exit除了用於tear things down,還可以進行異常的監控和處理,注意後幾個引數。要跳過乙個異常,只需要返回該函式true即可。
下面的樣例**跳過了所有的typeerror,而讓其他異常正常丟擲。
def
__exit__
(self, type, value, traceback):
return isinstance(value, typeerror)
上文說了exit函式可以進行部分異常的處理,如果我們不在這個函式中處理異常,他會正常丟擲,這時候我們可以這樣寫(python 2.7及以上版本,之前的版本參考使用contextlib.nested這個庫函式):
try:
with
open( "a.txt" ) as f :
do something
except ***error:
do something about exception
總之,with-as表示式極大的簡化了每次寫finally的工作,這對保持**的優雅性是有極大幫助的。
如果有多個項,我們可以這麼寫:
with
open("x.txt") as f1, open('***.txt') as f2:
do something with f1,f2
因此,python的with語句是提供乙個有效的機制,讓**更簡練,同時在異常產生時,清理工作更簡單。 Python學習 python陣列模組用法
array模組是python中實現的一種高效的陣列儲存型別。它和list相似,但是所有的陣列成員必須是同一種型別,因此在建立陣列的時候,就確定了陣列的型別 計算機為陣列分配一段連續的記憶體,從而支援對陣列隨機訪問 由於項的位址在編號上是連續的,陣列某一項的位址可以通過將兩個值相加得出,即將陣列的基本...
python 學習 筆記 format 用法
習慣了用 print s 這種結構來格式化輸出,今天無意中看到python 有format函式,讀了一遍它的幫助文件。使用起來還是比較方便的。摘錄出來。基本的按順序輸出 python版本需要2.7以上 format a b c a b c 輸出順序可以調整 format a b c b a c 右對...
python學習 while True的用法
在學習過程中,經常能遇到採用while true的用法。下面以乙個例子進行說明 建立乙個使用者登入系統,使用者輸入使用者名稱和密碼,如果正確就可以進入系統。1 我自己最開始的寫法 d 資料庫字典,所有使用者的使用者名稱密碼儲存在此 name input 請輸入您的使用者名稱 if name in d...