1. 程式人生 > >關於python中with as 的使用

關於python中with as 的使用

 其實with as 是python的控制流語句,像if ,while等的,只是比那個難理解罷了

首先我先摘抄一段別人的程式碼大體上給你們理解理解

首先請看下邊的解釋:

是不是不明白,其實我看了也覺得不明白,很暈,很繞,

下面給大家解釋一下,所謂上下文管理協議,其實是指with後面跟的ecception一般是一個類的實體,這個類的實體要包含__enter____exit__函式的定義才行

這個類嗎 想必大家都知道了,還有try/finally  try/except等等這些異常處理方法我就不解釋了。我就直奔正題。對於__enter____exit__方法這兩個方法被稱為 魔術方法  。其實是python的內建函式

,那麼這兩個方法到底是怎麼用的那,我們來看一個例子

class Closer:

def __init(self,obj):
   self.obj = obj
def __enter__(self):
   return self.obj

def __exit__(sekf,exception_type,exception_val,trace)

try:

   self.obj.close()

except AttributeError:

   print "NOt closable"
   return True




這是才定義一個叫做Closer的類,我們看一下這個類中有什麼

1. 一個__init__方法,__init__方法是個魔術方法,就是內建方法,在類初始化物件的時候被執行,起到初始化的作用

2. 一個__enter__方法,專門用於with  的一個內建方法,他的返回值要跟with as 語句中跟在as 後邊的variable.

3. 一個__exit__方法,用於with 語句的一個內建方法當with as語句中的with-block被執行或者終止後,這個類的物件應該做什麼,如果這個程式碼執行成功,則exception_type, exception_val。trace輸入值都是空,如果程式碼出錯了,就會變成像try/exception/finally語句一樣

with exception as varable  
   with-block

它的執行過程是:

首先執行exception 裡面的__enter__函式,它的返回值會賦給as 後邊的variable。像讓他返回什麼就返回什麼,只要你知道怎麼處理就行了,如顆不寫 as variable ,返回值就會被忽略。然後,開始執行with-block中的語句,不論成功失敗(比如發生異常,錯誤,設定sys.exit()),在with-block執行完成後,會執行expection中的__exit__函式

然後可能有的同學會問,這又跟try/finally有什麼關係呢,其實這樣的過程等價與

try:
    執行__enter__的內容
    執行 with_block
finally:
   執行__exit__內容

這就應該懂了吧 然後我們這時候再使用網上那些說的很迷的例子看一看  你就會明白了

class Sample(object):             # object類是所有類最終都會繼承的類
    def __enter__(self):          # 類中函式第一個引數始終是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__()

我們然後來分析一下程式是怎麼執行的

  • 首先我們呼叫get_sample()函式,返回Sample類
  • 執行Sample類中的__enter__()方法,列印"in__enter()"字串,並將字串“Foo”賦值給 as 後邊的sample變數;
  • 執行with__block程式碼塊,即列印"sample: %s"字串,結果為“sample Foo”
  • 執行with__block程式碼塊結束後,返回Sample()類,執行類方法__exit__().因為在執行with__block程式碼塊時並沒有錯誤返回,所以type,value,trace這三個argument都沒有值,直接列印print"in__exit__()"