檔案的io操作可以對檔案物件使用上下文管理,使用with…as語法。
with
open
('test'
)as f:
pass
如果希望類也支援上下文管理,則需要定義兩個函式。
classa:
def__init__
(self)
:print
('init'
)def
__enter__
(self)
:print
('enter'
)def
__exit__
(self,exc_type,exc_val,exc_tb)
:print
('exit'
)with a(
)as a:
print
(a)# a 此時為none
# 輸出:
# init
# enter
# none
# exit
進入with語句塊時,會呼叫__enter__,退出with語句塊時,呼叫__exit__。
因此,退出exit函式時,可以做清理工作,比如關閉檔案描述符。即使異常退出,也會執行上下文。因此,涉及到資源申請的操作,最好使用上下文管理語句。
當乙個物件同時實現了__enter__和__exit__方法時,它就屬於上下文管理物件。
方法意義
__enter__
進入與此物件相關的上下文。如果存在此方法,with語法會把該方法返回值作為繫結到as子句中指定的變數上
__exit__
class
point
:def
__init__
(self)
:print
('init'
)def
__enter__
(self)
:print
('enter'
)def
__exit__
(self,exc_type,exc_val,exc_tb)
:print
('exit'
)with point(
)as f:
raise exception(
'error'
)# 即使丟擲異常,也會執行exit。因此,上下文管理是安全的。即使sys.exit也是安全的
print
('do sth.'
)
注意:如果__exit__返回true,會壓制異常。
應用:使用上下文,實現函式計時器
class
timeit
:def
__init__
(self,fn)
: self.fn = fn
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
('{} took {}s'
.format
(self.fn.__name__,delta)
)with timeit(add)
as f:
print
(add(4,
6))
它是乙個裝飾器,裝飾乙個函式後可實現上下文管理。
而無需像類一樣實現__enter__和__exit__ 方法。
它對裝飾的函式是有要求的,必須有yield,也就是這個函式必須返回乙個生成器,且只有yield乙個值。
也就是這個裝飾器接收乙個生成器物件作為引數。
import contextlib
@contextlib.contextmanager
deffoo()
:print
('enter'
)# 相當於__enter__()
yield
5# yield的值只能有乙個,相當於__enter__方法的返回值
print
('exit'
)# 相當於__exit__()
with foo(
)as f:
print
(f)
輸出:
enter
5exit
f接收了yield語句的返回值。
但是很明顯無法保證exit的執行,如果產生了異常就直接退出。因此增加try finally。
import contextlib
@contextlib.contextmanager
deffoo()
:print
('enter'
)# 相當於__enter__()
try:
yield
5# yield的值只能有乙個,相當於__enter__方法的返回值
finally
:print
('exit'
)# 相當於__exit__()
with foo(
)as f:
raise exception(
)print
(f)
如此保證了enter和exit的正常執行。
當yield發生處為生成器函式增加了上下文管理,這是為函式增加上下文機制的方式:
因此,如果業務邏輯簡單可以使用函式加contextlib的裝飾器方式,如果業務複雜,則使用類的方式加__enter__和__exit__方法方便。
__getattr__
__setattr__
__delattr__
__getatrribute__
具體可參考《**python中的反射》
Python魔術方法 二
getattr 獲取屬性,類的屬性會按照mro順序找,找不到的話會執行getattr 方法,未設定的話,則會丟擲attributeerror異常。setattr 設定屬性,攔截對屬性的增加,修改操作,屬性要加到例項的dict 中,需要自己完成.delattr 可以阻止通過例項刪除屬性的操作,但是通過...
python 魔術方法
魔術方法 呼叫方式 解釋 new cls instance myclass arg1,arg2 new 在建立例項的時候被呼叫 init self instance myclass arg1,arg2 init 在建立例項的時候被呼叫 cmp self,other self other,self o...
Python魔術方法
參考文章 python 魔術方法指南 魔術方法,顧名思義是一種可以給物件 類 增加魔法的特殊方法,它們的表示方法一般是用雙下劃線包圍 如 init from os.path import join class fileobject 給檔案物件進行包裝從而確認在刪除時檔案流關閉 def init se...