1. 程式人生 > 其它 >python上下文管理器和else塊

python上下文管理器和else塊

目錄

前言

  • 本文討論python中的流程控制特性,主要包括兩個方面:
    1. with語句和上下文管理器,with語句會設定一個臨時的上下文,交給上下文管理器控制,並且負責清理上下文。
    2. for while try 語句中的else子句

if語句之外的else塊

for/else

  • 只有當for迴圈執行完畢,即沒有被break停止時,才執行else模組。如下例子,如果找到了banana,那麼迴圈就會提前終止,則else子句不會執行。

try/else

  • 僅當try塊中沒有異常丟擲時才執行else塊。如下例子,左邊不用else子句,只有當dangerous_call不丟擲異常的時候,after_call才會執行,但是這樣程式碼邏輯不夠清晰,於是可以改成右邊。

while/else

  • 僅當while迴圈執行完畢,即迴圈條件為False而正常退出迴圈時,才執行else塊,若while迴圈被break語句中止則不執行else塊。

上下文管理器物件和with塊

上下文管理器物件存在目的

  • 上下文管理器物件存在的目的是管理with語句,就像迭代器物件可以管理for語句一樣。

with語句存在目的

  • with語句存在目的是簡化try/finally模式。try/finally模式保證在try塊中程式碼執行完畢後執行finally模組中的操作,即使try塊中的程式碼由於異常、return語句或sys.exit()呼叫而終止,也會執行finally模組中的操作。finally子句中的程式碼通常用於釋放重要的資源,或還原臨時變更的狀態。

上下文管理器物件協議

  • 上下文管理器協議包括__enter__和__exit__兩個方法,只要實現了__enter__和__exit__這兩個方法,就能作為with語句塊中的上下文管理器物件使用。
  • with語句開始執行時,會在上下文管理器物件上執行__enter__方法。
  • with語句執行結束後,會在上下文管理器物件上呼叫__exit__方法,__exit__方法來扮演finally子句的角色。

with語句使用案例---確保關閉檔案物件

  1. with語句後邊應該跟上一個上下文管理器物件,即實現了__enter__和__exit__方法的物件,這裡open()函式返回一個檔案物件(屬於TextTOWrapper類),檔案物件實現了上下文管理器協議,其__enter__方法返回self。這裡把__enter__方法的返回值繫結到fp上,即把檔案物件本身繫結在fp上,誰讓其__enter__方法返回self呢。
  2. 從fp中讀取一些資料。
  3. fp變數仍然可用,即fp不是區域性變數。與函式和模組不同,with塊並沒有定義新的作用域。
  4. 可以讀取fp物件的屬性。
  5. 但是不能在fp上執行I/O操作,因此with塊末尾會自動呼叫檔案物件的__exit__方法把檔案關閉。這裡需要注意,是呼叫檔案物件的__exit__方法,而不是呼叫__enter__方法返回值的__exit__方法,雖然在這個例子中兩個是同一個,因為__enter__返回self。
  6. with語句的as子句可選,但是對於open函式是必須有的,以便獲取檔案的引用。

@contextmanager把生成器函式變成上下文管理器

  • @contextmanager裝飾器在包contextlib中。
  • @contextmanager裝飾器可以裝飾一個生成器物件,使其變成一個上下文管理器,不用去實現__enter__和__exit__方法。
  • 這裡的生成器物件是用於生成上下文管理的,不適用於迭代的,所以一般yield語句只執行一次,而不是用於迭代時候會產出很多元素。
  • 在使用@contextmanager裝飾的生成器中,yield語句的作用是把函式的定義體分為兩部分:
    • yield語句前面的所有程式碼在with塊的開始,即直譯器呼叫__enter__方法時執行,充當__enter__方法的函式體。
    • yield語句後邊的程式碼在with塊結束時,即呼叫__exit__方法時執行,充當__exit__方法的函式體。