一 、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
'''
三、總結
自定義背景關系管理器來對軟體系統中的資源進行管理,比如資料庫連接、共享資源的訪問控制等,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/500740.html
標籤:Python
