檔案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語...