魔術方法之上下文管理

2021-09-30 01:21:24 字數 4471 閱讀 9985

檔案io操作可以對檔案物件使用上下文管理,使用with as語法。

with

open

('test'

)as f:

pass

仿照上例寫乙個自己的類,實現上下文管理

classa:

pass

with a(

)as f:

#attributeerror:__enter__

pass

提示屬性錯誤,沒有__enter__,看來需要這個類屬性,某些版本會顯示沒有__exit__

當乙個物件同時實現了__enter__()__exit__()方法。他就屬於上下文管理物件

方法意義

__enter__當with後面的物件進入上下文,如果存在該方法,with語法會把該方法的返回值繫結到as子句中指定的變數上

__exit__當with一句結束時,呼叫此物件的該方法,

class

point

:def

__init__

(self)

:print

('init---------------'

)def

__enter__

(self)

:print

('enter--------------'

)def

__exit__

(self, exc_type, exc_val, exc_tb)

:#該方法後3個形參為上下文期間產生異常時的資訊

print

(exc_type,exc_val,exc_tb,sep=

'\n'

)print

('exit---------------'

)with point(

)as p:1/

0print

('with---------'

)print

('end-------------'

)

例項化物件時,並不會呼叫enter,進入with語句塊呼叫__enter__方法,然後執行with語句裡面的內容。

當碰到除0異常時,程式會呼叫__exit__方法,並把異常資訊傳入,如果此時該方法的返回值等效為true,則會壓制異常。

with可以開啟乙個上下文執行環境,在執行前做一些準備工作,執行後做一些收尾工作

注意:with並不會開啟乙個新的作用域

接下來看乙個極端例子

呼叫sys.exit(),會退出當前直譯器。

import sys

class

point

:def

__init__

(self)

:print

('init---------------'

)def

__enter__

(self)

:print

('enter--------------'

)return

10def

__exit__

(self, exc_type, exc_val, exc_tb)

:#該方法後3個形參為上下文期間產生異常時的資訊

print

(exc_type,exc_val,exc_tb,sep=

'\n'

)print

('exit---------------'

)with point(

)as p:

print

(p) sys.exit(1)

1/0

從執行結果來看,with語句把__enter__方法的返回值通過as子句繫結到p,之後執行其內部語句,當執行到sys.exit(1)時退出了python的執行環境,但依然執行了__exit__方法。

說明上下文管理很安全

#方法1,使用函式裝飾器顯示該函式的執行時長

from functools import wraps

import datetime,time

deftimeit

(fn)

: @wraps(fn)

def(

*args,

**kwargs)

: start = datetime.datetime.now(

) ret = fn(

*args,

**kwargs)

delta =

(datetime.datetime.now(

)- start)

.total_seconds(

)print

(delta)

return ret

@timeit

defadd

(x, y)

: time.sleep(2)

return x + y

print

(add(5,

6),add.__name__)

#方法2,使用上下文管理方法來顯示該函式的執行時長

import datetime,time

class

timeit

:def

__init__

(self,fn)

: self.fn = fn

def__enter__

(self)

: self.start = datetime.datetime.now(

)return self.fn

def__exit__

(self,exc_typy,exc_val,exc_tb)

: delta =

(datetime.datetime.now(

)- self.start)

.total_seconds(

)print

(delta)

defadd

(x, y)

: time.sleep(2)

return x + y

with timeit(add)

as fn:

fn(5,

6)

1.增強功能

在**執行的前後增加**,以增強其功能,類似裝飾器。

2.資源管理

​ 開啟資源需要關閉,例如檔案物件,網路物件,資料鏈結等。

3.許可權驗證

​ 在執行**前,做許可權驗證,在__enter__中處理。

contextlib.contextmanager是乙個裝飾器實現了上下文管理,裝飾乙個函式,而不像類一樣實現__enter____exit__方法。

其對下面的函式有所要求:

必須有yield,也就時函式必須返回乙個生成器,並且只有乙個yield值。

也就是這個裝飾器接收乙個生成器作為引數。

from contextlib import contextmanager

import sys

@contextmanager

deffoo()

:print

('enter---------'

)#相當於enter

try:

yield

5#yield的值只能由乙個,作為enter方法的返回值

finally

:print

('exit-----------'

)#相當於exit

with foo(

)as fn:

print

(fn)

sys.exit(

1)

當yield發生處為生成器增加乙個上下文管理,這是為函式增加上下文機制的方式。上例中用異常捕獲語句的目的是當with結構內部發生異常時,保證能夠執行print(exit)

總結:如果業務邏輯簡單可以使用函式加contextlib.contextmanager裝飾器方式,如果業務複雜,用類的方式加__enter____exit__方法方便

總結:如果業務邏輯簡單可以使用函式加contextlib.contextmanager裝飾器方式,如果業務複雜,用類的方式加__enter____exit__方法方便

Python魔術方法之上下文管理

魔術方法 上下文管理 檔案io操作可以對檔案物件使用上下文管理,使用with as語法 with open test as f pass 仿照上例寫乙個自己的類 提示錯誤 上下文管理物件 方法意義 enter進入與此物件相關的上下文,如果存在該方法,with語法會把該方法的返回值作為繫結到as子句中...

python的魔術方法之上下文管理

方法意義 enter 進入與此物件相關的上下文。如果存在該方法,with語法會把該方法的返回值作為繫結到as子句中指定的變數上 exit 退出與此物件相關的上下文。import time class point def init self print 1 init time.sleep 1 prin...

魔術方法 上下文管理

檔案io操作可以對檔案物件使用上下文管理,使用with as語法 上下文管理物件 方法意義 enter 進入與此物件相關的上下文.如果存在該方法,with語法會把該方法的返回值作為繫結到as子句中指定的變數上 exit 退出與此物件相關的上下文 例項化物件的時候,並不會呼叫enter,進入with語...