Python中with用法詳解


一 、with語句的原理

  • 上下文管理協議(Context Management Protocol):包含方法 __enter__()__exit__(),支持該協議的對象要實現這兩個方法。
  • 上下文管理器(Context Manager):支持上下文管理協議的對象,這種對象實現了__enter__()__exit__()方法。上下文管理器定義執行with語句時要建立的運行時上下文,負責執行with語句塊上下文中的進入與退出操作。通常使用with語句調用上下文管理器,也可以通過直接調用其方法來使用。

說完上面兩個概念,我們再從with語句的常用表達式入手,一段基本的with表達式,其結構是這樣的:

1 with EXPR as VAR:
2 
3     BLOCK

其中EXPR可以是任意表達式;as VAR是可選的。其一般的執行過程是這樣的:

  1. 執行EXPR,生成上下文管理器context_manager;
  2. 獲取上下文管理器的__exit()__方法,並保存起來用於之后的調用;
  3. 調用上下文管理器的__enter__()方法;如果使用了as子句,則將__enter__()方法的返回值賦值給as子句中的VAR;
  4. 執行BLOCK中的表達式;
  5. 不管是否執行過程中是否發生了異常,執行上下文管理器的__exit__()方法,__exit__()方法負責執行“清理”工作,如釋放資源等。如果執行過程中沒有出現異常,或者語句體中執行了語句break/continue/return,則以None作為參數調用__exit__(None, None, None);如果執行過程中出現異常,則使用sys.exc_info得到的異常信息為參數調用__exit__(exc_type, exc_value, exc_traceback)
  6. 出現異常時,如果__exit__(type, value, traceback)返回False,則會重新拋出異常,讓with之外的語句邏輯來處理異常,這也是通用做法;如果返回True,則忽略異常,不再對異常進行處理。

二、自定義上下文管理器

  Pythonwith語句是提供一個有效的機制,讓代碼更簡練,同時在異常產生時,清理工作更簡單。

 1 # coding = utf-8
 2 # 2019/7/19  Luckyxxt:有趣的事,Python永遠不會缺席!
 3 #!/usr/bin/env python
 4 
 5 class DBManager(object):
 6     def __init__(self):
 7         pass
 8 
 9     def __enter__(self):
10         print('__enter__')
11         return self
12 
13     def __exit__(self, exc_type, exc_val, exc_tb):
14         print('__exit__')
15         return True
16 
17 def getInstance():
18         return DBManager()
19 
20 with getInstance() as dbManagerIns:
21     print('with demo')

  with后面必須跟一個上下文管理器,如果使用了as,則是把上下文管理器的 __enter__() 方法的返回值賦值給 target,target 可以是單個變量,或者由“()”括起來的元組(不能是僅僅由“,”分隔的變量列表,必須加“()”)

代碼運行結果如下:

1 '''
2 __enter__
3 with demo
4 __exit__
5 
6 '''

結果分析:當我們使用with的時候,__enter__方法被調用,並且將返回值賦值給as后面的變量,並且在退出with的時候自動執行__exit__方法

 1 class With_work(object):
 2     def __enter__(self):
 3         """進入with語句的時候被調用"""
 4         print('enter called')
 5         return "xxt"
 6 
 7     def __exit__(self, exc_type, exc_val, exc_tb):
 8         """離開with的時候被with調用"""
 9         print('exit called')
10 
11 
12 with With_work() as f:
13     print(f)
14     print('hello with')
1 '''
2 enter called
3 xxt
4 hello with
5 exit called
6 
7 '''

 

三、總結

  自定義上下文管理器來對軟件系統中的資源進行管理,比如數據庫連接、共享資源的訪問控制等。

       

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM