Python中的with關鍵字使用詳解
這篇文章主要介紹了Python 中的with關鍵字使用詳解的相關資料,在Python中,with關鍵字是一個替你管理實現上下文協議對象的好東西,需要的朋友可以參考下
">
在Python 2.5 中, with 關鍵字被加入。它將常用的try ... except ... finally ... 模式很方便的被重複使用。過程中發生了一個異常,那麼在這個異常被拋出前,程式會先將被開啟的檔案關閉。的時候,常常會用類似這樣的程式碼:
with open('file.txt') as f: content = f.read()
如果將發起事務請求的操作變成可以支援with 關鍵字的,那麼用像這樣的程式碼就可以了:
db.begin() try: # do some actions except: db.rollback() raise finally: db.commit()
下面,詳細的說明一下with 的執行過程,並用兩個常用的方式實作上面的程式碼。
表達式,其結構是這樣的:
with transaction(db): # do some actions
#其中: EXPR 可以是任意表達式;as VAR 是可選的。
計算EXPR ,並取得一個上下文管理器。#呼叫上下文管理器的enter() 方法。
執行BLOCK 中的運算式。異常導致程式退出,那麼異常的type 、 value 和traceback (即sys.exc_info()的回傳值)將會作為參數傳遞給exit() 方法。
#將這個過程用程式碼表示,是這樣的:with EXPR as VAR: BLOCK
- 如果上下文管理器中沒有enter() 或exit() 中的任意一個方法,那麼解釋器會拋出一個AttributeError 。
在 BLOCK 中發生異常後,如果 exit() 方法回傳一個可被看成是 True 的值,那麼這個例外就不會被拋出,後面的程式碼就會繼續執行。
接下來,用兩種方法來實現上面來實現上面的過程的吧。 實作上下文管理器類別
第一種方法是實作一個類,其含有一個實例- 屬性
db 和上下文管理器所需要的方法enter() 和exit() 。
mgr = (EXPR) exit = type(mgr).exit # 这里没有执行 value = type(mgr).enter(mgr) exc = True try: try: VAR = value # 如果有 as VAR BLOCK except: exc = False if not exit(mgr, *sys.exc_info()): raise finally: if exc: exit(mgr, None, None, None)
登入後複製了解 with 的執行過程後,這個實作方式是很容易理解的。以下介紹的實作方式,其原理理解起來要複雜很多。 - 使用 產生器
- 裝飾器 在Python的標準函式庫中,有一個裝飾器可以透過生成器取得上下文管理器。使用生成器裝飾器的實作過程如下:
-
class transaction(object): def init(self, db): self.db = db def enter(self): self.db.begin() def exit(self, type, value, traceback): if type is None: db.commit() else: db.rollback()
登入後複製第一眼上看去,這種實作方式更為簡單,但其機制更為複雜。看看其執行過程:
Python解釋器辨識到yield 關鍵字後, def 會建立一個生成器
函數取代常規的函數(在類別定義之外我喜歡用函數代替方法)。
with 表达式调用实例对象的上下文管理器的 enter() 方法。
enter() 方法中会调用这个生成器的 next() 方法。这时候,生成器方法会执行到 yield db 处停止,并将 db 作为 next() 的返回值。如果有 as VAR ,那么它将会被赋值给 VAR 。
with 中的 BLOCK 被执行。
BLOCK 执行结束后,调用上下文管理器的 exit() 方法。 exit() 方法会再次调用生成器的 next() 方法。如果发生 StopIteration 异常,则 pass 。
如果没有发生异常生成器方法将会执行 db.commit() ,否则会执行 db.rollback() 。
再次看看上述过程的代码大致实现:
def contextmanager(func): def helper(*args, **kwargs): return GeneratorContextManager(func(*args, **kwargs)) return helper class GeneratorContextManager(object): def init(self, gen): self.gen = gen def enter(self): try: return self.gen.next() except StopIteration: raise RuntimeError("generator didn't yield") def exit(self, type, value, traceback): if type is None: try: self.gen.next() except StopIteration: pass else: raise RuntimeError("generator didn't stop") else: try: self.gen.throw(type, value, traceback) raise RuntimeError("generator didn't stop after throw()") except StopIteration: return True except: if sys.exc_info()[1] is not value: raise
总结
Python的 with 表达式包含了很多Python特性。花点时间吃透 with 是一件非常值得的事情。
一些其他的例子
锁机制
@contextmanager def locked(lock): lock.acquired() try: yield finally: lock.release()
标准输出重定向
@contextmanager def stdout_redirect(new_stdout): old_stdout = sys.stdout sys.stdout = new_stdout try: yield finally: sys.stdout = old_stdout with open("file.txt", "w") as f: with stdout_redirect(f): print "hello world"
以上是Python中的with關鍵字使用詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Linux終端中查看Python版本時遇到權限問題的解決方法當你在Linux終端中嘗試查看Python的版本時,輸入python...

使用FiddlerEverywhere進行中間人讀取時如何避免被檢測到當你使用FiddlerEverywhere...

在使用Python的pandas庫時,如何在兩個結構不同的DataFrame之間進行整列複製是一個常見的問題。假設我們有兩個Dat...

Uvicorn是如何持續監聽HTTP請求的? Uvicorn是一個基於ASGI的輕量級Web服務器,其核心功能之一便是監聽HTTP請求並進�...

如何在10小時內教計算機小白編程基礎?如果你只有10個小時來教計算機小白一些編程知識,你會選擇教些什麼�...

攻克Investing.com的反爬蟲策略許多人嘗試爬取Investing.com(https://cn.investing.com/news/latest-news)的新聞數據時,常常�...
