一 、with語句的原理 上下文管理協議(Context Management Protocol):包含方法 __enter__()和__exit__(),支持該協議的對象要實現這兩個方法。 上下文管理器(Context Manager):支持上下文管理協議的對象,這種對象實現了__enter__( ...
一 、with語句的原理
上下文管理協議(Context Management Protocol):包含方法 __enter__()
和__exit__()
,支持該協議的對象要實現這兩個方法。
上下文管理器(Context Manager):支持上下文管理協議的對象,這種對象實現了__enter__()
和__exit__()
方法。上下文管理器定義執行with語句時要建立的運行時上下文,負責執行with語句塊上下文中的進入與退出操作。通常使用with語句調用上下文管理器,也可以通過直接調用其方法來使用。
說完上面兩個概念,我們再從with語句的常用表達式入手,一段基本的with表達式,其結構是這樣的:
with EXPR as VAR:
BLOCK
其中EXPR可以是任意表達式;as VAR是可選的。其一般的執行過程是這樣的:
- 執行EXPR,生成上下文管理器context_manager;
- 獲取上下文管理器的
__exit()__
方法,並保存起來用於之後的調用; - 調用上下文管理器的
__enter__()
方法;如果使用了as子句,則將__enter__()
方法的返回值賦值給as子句中的VAR; - 執行BLOCK中的表達式;
- 不管是否執行過程中是否發生了異常,執行上下文管理器的
__exit__(
)方法,__exit__()
方法負責執行“清理”工作,如釋放資源等。如果執行過程中沒有出現異常,或者語句體中執行了語句break/continue/return,則以None作為參數調用__exit__(None, None, None)
;如果執行過程中出現異常,則使用sys.exc_info得到的異常信息為參數調用__exit__(exc_type, exc_value, exc_traceback)
; - 出現異常時,如果
__exit__(type, value, traceback)
返回False,則會重新拋出異常,讓with之外的語句邏輯來處理異常,這也是通用做法;如果返回True,則忽略異常,不再對異常進行處理。
二、自定義上下文管理器
Python的with語句是提供一個有效的機制,讓代碼更簡練,同時在異常產生時,清理工作更簡單。
class DBManager(object):
def __init__(self):
pass
def __enter__(self):
print('__enter__')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('__exit__')
return True
def getInstance():
return DBManager()
with getInstance() as dbManagerIns:
print('with demo')
with後面必須跟一個上下文管理器,如果使用了as,則是把上下文管理器的 __enter__()
方法的返回值賦值給 target,target 可以是單個變數,或者由“()”括起來的元組(不能是僅僅由“,”分隔的變數列表,必須加“()”)
代碼運行結果如下:
'''
__enter__
with demo
__exit__
'''
結果分析:當我們使用with的時候,__enter__
方法被調用,並且將返回值賦值給as後面的變數,並且在退出with的時候自動執行__exit__
方法
'''
學習中遇到問題沒人解答?小編創建了一個Python學習交流群:711312441
尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書!
'''
class With_work(object):
def __enter__(self):
"""進入with語句的時候被調用"""
print('enter called')
return "xxt"
def __exit__(self, exc_type, exc_val, exc_tb):
"""離開with的時候被with調用"""
print('exit called')
with With_work() as f:
print(f)
print('hello with')
'''
enter called
xxt
hello with
exit called
'''
三、總結
自定義上下文管理器來對軟體系統中的資源進行管理,比如資料庫連接、共用資源的訪問控制等。