2010-09-28 41 views
4

我想了解Python中的語句。我到處看到它打開和關閉一個文件的談話,並且意味着替換try-finally塊。有人可以發佈一些其他的例子。我只是嘗試了燒瓶,並有聲明在其中。絕對要求某人提供一些清晰的信息。Python「with」語句用於什麼?

回答

9

有一個非常好的解釋here。基本上,with語句在關聯對象上調用兩個特殊方法。 __enter__和__exit__方法。 enter方法返回與「with」語句關聯的變量。雖然__exit__方法在執行語句以處理任何清理(例如關閉文件指針)後被調用。

+2

我與OP。您給出的鏈接演示了Alice描述的「打開和關閉文件」示例,但它實際上並未顯示*爲什麼*它比「data = open(」x.txt「)。read()」更好。看起來「有了」是我應該考慮的事情,但如果我能說出它的實際效果,我就會感到厭煩。 – 2010-09-28 19:24:13

+1

使用它來避免在完成某些事情後不得不記住或處理任何清理的關鍵原因。 with block爲你做到了這一點。因此,而不是fp = open()... fp.close()。你只是使用一個塊。 – GWW 2010-09-28 20:33:17

+1

但這裏有什麼大不了的。終於嘗試塊更清晰,更清晰,如下所述:顯式比隱式更好! :-) – Rasmus 2010-09-29 02:38:11

9

with陳述的想法是讓「做正確的事」成爲阻力最小的路徑。雖然文件的例子是最簡單的,線程鎖實際提供的無明顯缺陷代碼比較經典的例子:

try: 
    lock.acquire() 
    # do stuff 
finally: 
    lock.release() 

該代碼被打破 - 如果鎖定獲取以往任何時候都失敗了,要麼有錯誤,會引發異常(因爲代碼會嘗試釋放它從未獲取的鎖),或者更糟的是,如果這是一個遞歸鎖,它將會提前發佈。正確的代碼如下所示:

lock.acquire() 
try: 
    # do stuff 
finally: 
    # If lock.acquire() fails, this *doesn't* run 
    lock.release() 

通過使用with聲明,就不可能得到這個錯誤的,因爲它是建立在上下文管理器:

with lock: # The lock *knows* how to correctly handle acquisition and release 
    # do stuff 

其他地方,with語句非常類似於函數和類裝飾器的主要好處:它需要「兩件式」代碼,可以用任意數量的代碼行分開(裝飾器的函數定義,當前案例中的try塊)並將其轉化爲程序員si所在的「單件」代碼mply宣稱他們正在嘗試做什麼。

對於簡短的例子,這看起來不像是一個大的收穫,但它實際上在審查代碼時會產生巨大的差異。當我在一段代碼中看到lock.acquire()時,我需要向下滾動並檢查相應的lock.release()。當我看到with lock:,但是,不需要這樣的檢查 - 我可以立即看到鎖將被正確釋放。

+0

您是否介意在不使用'with'語句的情況下編寫* correct *實現的例子來添加您的答案? – max 2016-08-04 16:58:43

+0

@max好點 - 加入! – ncoghlan 2016-08-18 03:07:57

1

有在PEP343使用with,包括文件打開示例12個示例:

  1. 一種用於確保一個鎖,在 塊的開始獲得的,是當該塊是釋放的模板左
  2. 一種用於開口確保所述文件的文件模板被關閉 當塊被左
  3. 一種用於提交或回滾數據庫 交易
  4. 模板
  5. 實施例1改寫而不發電機
  6. 重定向標準輸出暫時
  7. 上打開()也將返回錯誤條件
  8. 另一個有用的實施例將是一個操作的變體,其塊 信號
  9. 另一種用途爲這個特點是小數情況下
  10. 下面是小數模塊
  11. 一個通用的「對象閉」上下文管理簡單上下文管理
  12. 通過交換acquire()和release()調用,釋放()上下文以臨時釋放先前獲取的鎖。
  13. 「嵌套」上下文管理器,自動從左到右嵌套 提供的上下文以避免過多 縮進