面試題: with語句操作的物件必須是上下文管理器。
那麼,到底什麼是上下文管理器呢?
簡單的理解,擁有 __ enter__() 和 __ exit__() 方法的物件就是上下文管理器。
__ enter__(self):進入上下文管理器自動呼叫的方法,在 with 執行之前執行。如果 有 as子句,該方法的返回值被賦值給 as 子句後的變數;該方法可以返回多個值。
__ exit__(self, exc_type, exc_value, exc_traceback):退出上下文管理器自動呼叫的方法。在with 執行之後執行(不管有無異常)。
當 with … as … 操作上下文管理器時,就會在執行語句體之前,先執行上下文管理器的 __ enter__() 方法,
然後再執行語句體,最後執行 __ exit__() 方法。
構建上下文管理器,常見的有 2 種方式:基於類實現和基於生成器實現。
在對檔案的操作中,我們通常使用with open(『filename』)as f開啟檔案,下面我們用__enter__()和__exit__()這兩個方法,自己構造乙個上下文管理器,以便能夠使用with語句操作。
class
open
(object):
def__init__
(self,filename)
: self.filename = filename
def__enter__
(self)
: self.f =
open
(self.filename)
return self.f
def__exit__
(self, exc_type, exc_val, exc_tb)
: self.f.close(
)#open就是上下文管理器。 擁有 __enter__() 和 __exit__() 方法的物件就是上下文管理器
with open(
'./example.log'
)as f:
print
(f.readlines(
))
當遇到with語句時,__ enter__()方法首先被觸發執行。__ enter__()的返回值(如果有的話)被放置在由as限定的變數中。之後開始執行with**塊中的語句。最後__ exit__()方法被觸發來執行清理工作。
這種形式的控制流與with語句塊中發生了什麼情況是沒有關聯的,出現異常時也是如此。
__ exit__(self, exc_type, exc_val, exc_tb)方法中這三個引數包含了異常型別、異常值、對掛起異常的追溯(如果出現異常的話)。__ exit__()可以選擇以某種方式來使用異常資訊,或者什麼也不幹直接忽略並返回none作為結果。如果__ exit__()的返回值為true,異常會被清理乾淨,程式會立即執行with語句塊之後的內容。
from contextlib import contextmanager
import time
@contextmanager
deftimethis
(label)
: start = time.time(
)try
:yield
finally
: end = time.time(
)print
('{}:{}'
.format
(label,end-start)
)with timethis(
'counting:'):
n =1000000
while n>0:
n -=
1
在timethis()函式中,所有位於yield之前的**會作為上下文管理器的__ enter__()方法來執行;而所有在yield之後的**會作為__ exit__()方法執行。如果有異常產生,則會在yield語句中丟擲。
@contextmanager只適用於編寫自給自足型的上下文管理器函式
如果有一些物件(比如檔案、鎖、網路連線)需要支援在with語句中使用,那還是需要分別實現__enter__()和__exit__()方法
python 列表方法 44
alist 1,2,3,bob alice alist 0 10 列表腳標為0的字元改為10 alist 10,2,3,bob alice alist 1 3 20,30 將列表腳標為1,2 不包括3 的字元改為20和30 alist 10,20,30,bob alice alist 2 2 22,...
python學習44 使用 slots
python可以在執行期間,動態新增屬性,slots 可以限定物件的屬性,不讓隨意新增,比如下面這個例子,就是限定了score,name屬性,所以下面s1.score是成功的,s2.age就是失敗的。1 slots限定只對當前的類有效,對子類無效,如果想子類也有限定,需要子類裡面去定義slots。2...
C 44 函式引數的秘密 (上)
下面的程式輸出什麼?為什麼呢?int k 1 printf d,d n k k include int func int i,int j int main 輸出 gcc i 2,j 1 3特別說明 此處暫時沒有找到有其它求值順序的編譯器來輸出說明。由於c語言未明確規定函式引數的求值順序,其交由具體的...