檔案io操作可以對檔案物件使用上下文管理,使用with…as語法
上下文管理物件
方法意義
__enter__
進入與此物件相關的上下文.如果存在該方法,with語法會把該方法的返回值作為繫結到as子句中指定的變數上
__exit__
退出與此物件相關的上下文
例項化物件的時候,並不會呼叫enter,進入with語句塊呼叫__enter__方法,然後執行語句體,最後離開with語句塊的時候,呼叫__exit__方法
with可以開啟乙個上下文執行環境,在執行前做一些準備工作,執行後做一些收尾工作
注意,with並不開啟乙個新的作用域
上下文管理的安全性
class point:
def __init__(self):
print('init')
def __enter__(self):
print("enter")
def __exit__(self,exc_type,exc_val,exc_tb):
print('exit')
f = point()
with f as p:
import sys
sys.exit(1)
print(f==p)
從執行結果來看,依然執行__exit__函式,哪怕是退出python執行環境
說明上下文管理很安全
class point:
def __init__(self):
print('init')
def __enter__(self):
print("enter")
def __exit__(self,exc_type,exc_val,exc_tb):
print('exit')
#return 1 #壓制異常
p = open('t1.py')
with p as f:
print(f)
print(p)
print(f is p) #true
print(f == p) #true
f = point()
with f as p:
print(f==p) #flase
問題在__enter__方法上,它將自己的返回值賦給f,修改上例
with語法,會呼叫with後的物件__enter__方法,如果有as,則將該方法的返回值賦給as子句的變數
上例,可以等價為f = p.__enter__()
方法的引數
enter,沒有其他引數
exit,方法有三個引數(self,exc_type,exc_val,exc_tb)
這三個引數都與異常有關
如果該上下文退出時沒有異常,這三個引數都為none
如果有異常,引數意義如下
exc_type,異常型別
exc_val,異常的值
exc_tb(traceback),異常的追蹤資訊
__exit__方法返回乙個等效true的值,則壓制異常;否則,繼續丟擲異常
練習為加法函式計時
使用裝飾器顯示該函式的執行時長
使用上下文管理來顯示該函式的執行時長
import datetime
import time
def lagger(fn):
@wraps(fn)
def warrapr(*args,**kwargs):
statr = datetime.datetime.now()
ret = fn(*args,**kwargs)
datel = '{}s'.format((datetime.datetime.now()-statr).total_seconds())
print(datel)
return ret
return warrapr
@lagger
def add(x,y):
"""12312"""
time.sleep(2)
return x+y
print(add(10,10))
class point:
"""abddadss"""
def __init__(self,fn):
self.fn = fn
# self.__name__ = fn.__name__
# self.__doc__ = fn.__doc__
def __enter__(self):
self.start = datetime.datetime.now()
return self.fn
def __exit__(self, exc_type, exc_val, exc_tb):
delta = (datetime.datetime.now()-self.start).total_seconds()
print('{}s'.format(delta))
with point(add) as f:
print(add(4,5))
用類當字串
import datetime
import time
class point:
"""abddadss"""
def __init__(self,fn):
self.fn = fn
# self.__name__ = fn.__name__
# self.__doc__ = fn.__doc__
def __enter__(self):
self.start = datetime.datetime.now()
return self.fn
def __exit__(self, exc_type, exc_val, exc_tb):
delta = (datetime.datetime.now()-self.start).total_seconds()
# print(delta)
# print(exc_tb)
# print(exc_type)
# print(exc_val)
# print("~~~~~~~~~~~")
def __call__(self, *args, **kwargs):
statr = datetime.datetime.now()
ret = self.fn(*args,**kwargs)
datel = (datetime.datetime.now()-statr).total_seconds()
print(datel)
return ret
@point
def add(x,y):
"""12312"""
time.sleep(2)
return x+y
print(add(10,10))
上面的類可以用在上下文管理,也可以用作字串
1.增強功能
在**執行的前後增加**,以增強其功能.類似裝飾器的功能
2.資源管理
開啟了資源需要關閉,例如檔案物件 網路連線 資料庫連線等
3.許可權驗證
在執行**之前,做許可權的驗證,在__enter__中處理
contextlib.contextmanager
它是乙個裝飾器實現上下文管理,裝飾乙個函式,而不用像類一樣實現__enter__和__exit__方法
對下面的函式有要求:必須有yield,也就是這個函式必須返回乙個生成器,且只有yield乙個值
也就是說這個裝飾器接收乙個生成器物件作為引數
import contextlib
@contextlib.contextmanager
def foo():
print('abc')
try:
yield
finally:
print('123')
with foo() as f:
raise exception()
print(f)
f接收yield語句的返回值
增加異常
增加try finally
當yield發生處為生成器函式增加了上下文管理.這是為函式增加上下文機制的方式
魔術方法之上下文管理
檔案io操作可以對檔案物件使用上下文管理,使用with as語法。with open test as f pass仿照上例寫乙個自己的類,實現上下文管理 classa pass with a as f attributeerror enter pass提示屬性錯誤,沒有 enter 看來需要這個類屬...
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...