国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Python函數(shù)-上下文管理器

這篇具有很好參考價值的文章主要介紹了Python函數(shù)-上下文管理器。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

函數(shù)-上下文管理器

上下文管理協(xié)議(Context Management Protocol):包含方法 enter() 和 exit(),支持該協(xié)議的對象要實現(xiàn)這兩個方法。

上下文管理器(Context Manager):支持上下文管理協(xié)議的對象,這種對象實現(xiàn)了__enter__() 和 exit() 方法。

上下文管理器定義執(zhí)行 with 語句時要建立的運行時上下文,負責(zé)執(zhí)行 with 語句塊上下文中的進入與退出操作。通常使用 with 語句調(diào)用上下文管理器,也可以通過直接調(diào)用其方法來使用。

運行時上下文(runtime context):由上下文管理器創(chuàng)建,通過上下文管理器的 enter() 和__exit__() 方法實現(xiàn),enter() 方法在語句體執(zhí)行之前進入運行時上下文,exit() 在語句體執(zhí)行完后從運行時上下文退出。with 語句支持運行時上下文這一概念。

上下文表達式(Context Expression):with 語句中跟在關(guān)鍵字 with 之后的表達式,該表達式要返回一個上下文管理器對象。

語句體(with-body):with 語句包裹起來的代碼塊,在執(zhí)行語句體之前會調(diào)用上下文管理器的 enter() 方法,執(zhí)行完語句體之后會執(zhí)行__exit__() 方法。

01 with語句

with是從Python2.5引入的一個新的語法,它是一種上下文管理協(xié)議的具體實現(xiàn),目的在于從流程圖中把 try、except 和finally 關(guān)鍵字和 資源分配釋放相關(guān)代碼統(tǒng)統(tǒng)去掉,簡化try….except….finlally的處理流程。

with通過__enter__方法初始化,然后在__exit__中做善后以及處理異常。 所以使用with處理的對象必須有__enter__()和__exit__()這兩個方法。

其中__enter__()方法在語句體(with語句包裹起來的代碼塊)執(zhí)行之前進入運行,exit()方法在語句體執(zhí)行完畢退出后運行。

with 語句適用于對資源進行訪問的場合,確保不管使用過程中是否發(fā)生異常都會執(zhí)行必要的“清理”操作,釋放資源,比如文件使用后自動關(guān)閉、線程中鎖的自動獲取和釋放等。

With語句的基本語法格式:

with expression [as target]:
    with_body

'''
參數(shù)說明:
expression:是一個需要執(zhí)行的表達式;
target:是一個變量或者元組,存儲的是expression表達式執(zhí)行返回的結(jié)果,可選參數(shù)。            
with_body:是一段語句體。
'''

02 應(yīng)用場景

有一些任務(wù),可能事先需要設(shè)置,事后做清理工作。對于這種場景,Python的with語句提供了一種非常方便的處理方式。一個很好的例子是文件處理,用戶需要獲取一個文件句柄,從文件中讀取數(shù)據(jù),然后關(guān)閉文件句柄。

  • 文件操作
  • 進程線程之間互斥對象
  • 資源的加鎖和解鎖
  • 支持上下文其他對象

03 示例

# 不用with語句打開文件
f = open("test.txt")
print(f.read())
f.close()

'''
這里有兩個問題:
一是可能忘記關(guān)閉文件句柄; 
二是文件讀取數(shù)據(jù)發(fā)生異常,沒有進行任何處理。
'''
# 使用異常處理語句增強文件操作          
try:
    f = open('test.txt') 
    print(f.read())
except:
    print('fail to open') 
finally:
     f.close()           
'''
這里有一個問題:
雖然這段代碼運行良好,但是太冗長
'''
# 使用with上下文管理器          
with open('test.txt') as f:
    print(f.read())          
'''
有更優(yōu)雅的語法,
還可以很好的處理上下文環(huán)境產(chǎn)生的異常。
'''

with open('test.txt') as f:
    print(f.read())
    
print(f.closed)   # 返回True,說明文件句柄已經(jīng)被自動關(guān)閉

04 with工作原理

緊跟with關(guān)鍵字后面的表達式會被求值,表達式運算之后返回一個對象,該對象必須包含兩個方法:enter()和__exit__()。表達式運算之后,會調(diào)用對象的__enter__()方法,這個方法的返回值將被賦值給as關(guān)鍵字后面的變量。

當(dāng)with包含的代碼塊全部被執(zhí)行完之后,再調(diào)用前面返回對象的__exit__()方法。

針對上面示例,當(dāng)打開文件執(zhí)行操作時,具體流程如下:

  1. with語句先暫存了File類的__exit__?法

  2. 然后它調(diào)?File類的__enter__?法

  3. __enter__?法打開?件并返回給with語句

  4. 打開的?件句柄被傳遞給 f 參數(shù)

  5. 我們使?.read()來讀取?件

  6. with語句調(diào)?之前暫存的__exit__?法

  7. __exit__?法關(guān)閉了?件

#示例1,演示上下文運行全流程:
class Test:
    def __enter__(self):
        print("開始運行上下文")

    def __exit__(self, type, value, trace):
        print("結(jié)束運行上下文")


with Test():
    print("上下文運行中")
#示例2,如果with表達式運算結(jié)果不是上下文管理器,with將拋出異常:
class Test:
    pass


with Test():
    print("上下文運行中") 

'''
Traceback (most recent call last):
  File "d:/www_vs/test2.py", line 8, in <module>
    with test():
AttributeError: __enter__
'''
#示例3,完善上下文管理器
class Test:
    name = "上下文管理器"
    def __enter__(self):
        return self

    def __exit__(self, type, value, trace):
        print(type)
        print(value)        
        print(trace)  

with Test() as t:
    print(t.name)
    raise
'''
上下文管理器
<class 'RuntimeError'>
No active exception to reraise
<traceback object at 0x02BA7988>
Traceback (most recent call last):
  File "d:/www_vs/test3.py", line 13, in <module>
    raise
RuntimeError: No active exception to reraise
'''

通過示例3,可以看到__enter__()方法被執(zhí)行, enter()方法必須包含1個位置參數(shù)。該方法的返回值是this,賦值給變量t。

t表示Test的實例對象,執(zhí)行with代碼塊,打印實例對象的屬性name。然后,使用raise主動拋出異常。

exit()方法被調(diào)用。該方法必須包含4個位置參數(shù)。with真正強大之處是它可以處理異常。可能你已經(jīng)注意到__exit__方法后面三個參數(shù):type、 val 和 trace。 這些參數(shù)在異常處理中相當(dāng)有用,type表示異常類型,val表示異常的具體信息,trace表示具體錯誤細節(jié)。

實際上,如果在with后面的代碼塊拋出任何異常時,exit() 方法被執(zhí)行,與之關(guān)聯(lián)的type、value和stack trace傳給 exit() 方法,因此拋出的異常信息會被打印出來了。

在開發(fā)庫時,清理資源、 關(guān)閉文件等等操作,都可以放在 exit 方法中完成。另外,exit 還可以進行異常的監(jiān)控和處理。

注意,如果要跳過一個異常,只需要__exit__返回True即可。如果返回False,將拋出異常。

# 下面示例將跳過所有的TypeError,而讓其他異常正常拋出。
class Test:
    name = "上下文管理器"
    def __enter__(self):
        return self

    def __exit__(self, type, value, trace):
        return isinstance(value, TypeError) 

with Test() as t:
    print(t.name)
    raise TypeError()

總之,with-as表達式極大的簡化了每次寫finally的工作,這對保持代碼的優(yōu)雅性是有極大幫助的。如果有多個項,還可以如下面方式進行編寫。

with open("test1.txt", "w") as f1, open('test2.txt', "w") as f2:
    f1.write("test1")
    f2.write("test2")            

因此,Python的with語句提供了一個有效的機制,讓代碼更簡練,同時在異常產(chǎn)生時,清理工作更簡單。

當(dāng)異常發(fā)?時,with語句會采取哪些步驟。

  1. 它把異常的type,value和traceback傳遞給__exit__?法。

  2. 它讓__exit__?法來處理異常。

  3. 如果__exit__返回的是True,那么這個異常就被優(yōu)雅地處理了。

  4. 如果__exit__返回的是True以外的任何東西,那么這個異常將被with語句拋出。

05 應(yīng)用

自定義打開文件
class myOpen(object):
    def __init__(self,filename):
        self.handle=open(filename)
        print( "Resource:%s"%filename )
    def __enter__(self):
        print( "[enter %s]: 分配資源."%self.handle )
        return self.handle  # 可以返回不同的對象
    def __exit__(self,exc_type,exc_value,exc_trackback):
        print( "[exit %s]: 釋放資源." %self.handle )
        if exc_trackback is None:
            print( "[exit %s]: 無異常退出."%self.handle )
            self.handle.close()
        else:
            print( "[exit %s]: 包含異常的退出."%self.handle )
        return False # 可以省略,缺省的None也是被看做是False


with myOpen('test1.txt') as fp:
    for line in fp.readlines():
        print( line , " " )           
          
'''            
輸出結(jié)果:         
Resource:test1.txt
[enter <_io.TextIOWrapper name='test1.txt' mode='r' encoding='cp936'>]: 分配資源.
1 
2  
[exit <_io.TextIOWrapper name='test1.txt' mode='r' encoding='cp936'>]: 釋放資源.
[exit <_io.TextIOWrapper name='test1.txt' mode='r' encoding='cp936'>]: 無異常退出. 
'''

myOpen中的__enter__() 返回的是自身的引用,這個引用可以賦值給 as 子句中的fp變量; 返回值的類型可以根據(jù)實際需要設(shè)置為不同的類型,不必是上下文管理器對象本身。

exit() 方法中對變量exc_trackback進行檢測,如果不為 None,表示發(fā)生了異常,返回 False 表示需要由外部代碼邏輯對異常進行處理; 如果沒有發(fā)生異常,缺省的返回值為 None,在布爾環(huán)境中也是被看做 False,但是由于沒有異常發(fā)生,exit() 的三個參數(shù)都為 None,上下文管理代碼可以檢測這種情況,做正常處理。exit()方法的3個參數(shù),分別代表異常的類型、值、以及堆棧信息。

自定義上下文類
class Mycontex(object):
    def __init__(self,name):
        self.name=name
    def __enter__(self):
        print("進入enter")
        return self
    def do_self(self):
        print(self.name)
    def __exit__(self,exc_type,exc_value,traceback):
        print("退出exit")
        print(exc_type,exc_value)

with Mycontex('test') as mc:
    mc.do_self()            
            
'''
輸出結(jié)果:
進入enter
test
退出exit
None None
'''

自定義類必須包含上述幾個方法才能正確使用with關(guān)鍵字。即使程序發(fā)生了錯誤,Python解釋器終止了程序,但是我們的類 還是順利關(guān)閉了。

06 基于?成器的實現(xiàn)

還可以?裝飾器(decorators)和?成器(generators)來實現(xiàn)上下?管理器。

Python有個contextlib模塊專門?于這個?的。我們可以使??個?成器函數(shù)來實現(xiàn)? 個上下?管理器,?不是使??個類。

from contextlib import contextmanager

@contextmanager
def open_file(name):
    f = open(name, 'w')
    yield f
    f.close()

這個實現(xiàn)?式看起來更加直觀和簡單。然?,這個?法需要關(guān)于?成器、yield 和裝飾器的?些知識。在這個例?中我們還沒有捕捉可能產(chǎn)?的任何異常。它的?作?式 和之前的?法?致相同。

簡單剖析下這個?法。

  1. Python解釋器遇到了yield關(guān)鍵字。因為這個緣故它創(chuàng)建了?個?成器?不是?個 普通的函數(shù)。

  2. 因為這個裝飾器,contextmanager會被調(diào)?并傳?函數(shù)名(open_file)作為 參數(shù)。

  3. contextmanager函數(shù)返回?個以GeneratorContextManager對象封裝過的 ?成器。

  4. 這個GeneratorContextManager被賦值給open_file函數(shù),我們實際上是在 調(diào)?GeneratorContextManager對象。

那現(xiàn)在我們既然知道了所有這些,我們可以?這個新?成的上下?管理器了,像這樣:文章來源地址http://www.zghlxwxcb.cn/news/detail-658864.html

with open_file('some_file') as f:
    f.write('hola!')           

到了這里,關(guān)于Python函數(shù)-上下文管理器的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Python教程(27)——如何使用Python中的上下文管理器

    當(dāng)我們在編寫代碼時,經(jīng)常會遇到需要管理資源的情況,比如打開和關(guān)閉文件,如果遇到了一些異常情況,我們需要關(guān)閉資源,不然會導(dǎo)致資源泄露,雖然我們可以通過手動的方式來關(guān)閉,但如果有多個異常情況需要考慮的話,萬一不小心漏了一處,就芭比Q了。所以,如果有

    2024年02月19日
    瀏覽(23)
  • Python高級語法:with語句和上下文管理器

    Python高級語法:with語句和上下文管理器

    1.文件操作說明: ①文件使用完后必須關(guān)閉。 ②因文件對象會占用操作系統(tǒng)的資源,并且操作系統(tǒng)同一時間能打開的文件數(shù)量也是有限的。 例如:? 2. 存在的安全隱患: ① 由于文件讀寫時都有可能產(chǎn)生IOError,一旦出錯,后面的f.close()就不會調(diào)用。 例如: 運行結(jié)果: 3.try…except…

    2024年02月04日
    瀏覽(23)
  • 【 Python 全棧開發(fā) - WEB開發(fā)篇 - 38 】property和上下文管理器

    Python 是一個簡潔而強大的編程語言,通過提供各種特性和工具,使開發(fā)人員能夠更高效地進行編程。其中一個非常有用的特性是 @property 裝飾器,它允許我們在類中定義屬性并自定義其行為。 @property 裝飾器用于將一個方法轉(zhuǎn)換為類的屬性。使用 @property 裝飾器,我們可以像訪

    2024年02月13日
    瀏覽(36)
  • 【python】flask執(zhí)行上下文context,請求上下文和應(yīng)用上下文原理解析

    【python】flask執(zhí)行上下文context,請求上下文和應(yīng)用上下文原理解析

    ?? 歡迎大家來到景天科技苑?? ???? 養(yǎng)成好習(xí)慣,先贊后看哦~???? ?? 作者簡介:景天科技苑 ??《頭銜》:大廠架構(gòu)師,華為云開發(fā)者社區(qū)專家博主,阿里云開發(fā)者社區(qū)專家博主,CSDN新星創(chuàng)作者,掘金優(yōu)秀博主,51CTO博客專家等。 ??《博客》:Python全棧,前后端開

    2024年03月26日
    瀏覽(22)
  • 無限上下文,多級內(nèi)存管理!突破ChatGPT等大語言模型上下文限制

    無限上下文,多級內(nèi)存管理!突破ChatGPT等大語言模型上下文限制

    目前,ChatGPT、Llama 2、文心一言等主流大語言模型,因技術(shù)架構(gòu)的問題上下文輸入一直受到限制,即便是Claude 最多只支持10萬token輸入,這對于解讀上百頁報告、書籍、論文來說非常不方便。 為了解決這一難題,加州伯克利分校受操作系統(tǒng)的內(nèi)存管理機制啟發(fā),提出了MemGPT。

    2024年02月06日
    瀏覽(26)
  • 〖大前端 - 基礎(chǔ)入門三大核心之JS篇(51)〗- 面向?qū)ο笾J識上下文與上下文規(guī)則

    〖大前端 - 基礎(chǔ)入門三大核心之JS篇(51)〗- 面向?qū)ο笾J識上下文與上下文規(guī)則

    說明:該文屬于 大前端全棧架構(gòu)白寶書專欄, 目前階段免費 , 如需要項目實戰(zhàn)或者是體系化資源,文末名片加V! 作者:哈哥撩編程,十余年工作經(jīng)驗, 從事過全棧研發(fā)、產(chǎn)品經(jīng)理等工作,目前在公司擔(dān)任研發(fā)部門CTO。 榮譽: 2022年度博客之星Top4、2023年度超級個體得主、谷

    2024年02月05日
    瀏覽(30)
  • 學(xué)習(xí)筆記整理-面向?qū)ο?02-認識函數(shù)的上下文

    什么是上下文 函數(shù)的上下文 函數(shù)中可以使用 this ,它表示 函數(shù)的上下文 。 與中文中\(zhòng)\\"這\\\"類似,函數(shù)中的this具體指代什么 必須通過調(diào)用函數(shù)時的\\\"前言后語\\\"來判斷 函數(shù)中的this 函數(shù)的上下文由調(diào)用方式?jīng)Q定 同一個函數(shù),用不同的形式調(diào)用它,則函數(shù)的上下文不同 情形

    2024年02月13日
    瀏覽(19)
  • Zustand 和 React 上下文狀態(tài)管理

    Zustand 和 React 上下文狀態(tài)管理

    Zustand 是客戶端全局狀態(tài)管理的一個很棒的庫。它簡單、快速,并且包大小小。然而,有一件事我不一定喜歡它:這些 Store 是全局性的。 但這不是全局狀態(tài)管理的重點嗎?要使該狀態(tài)在您的應(yīng)用程序中隨處可用。不過當(dāng)我回顧過去幾年中使用 zustand 的情況時,我意識到,更多

    2024年04月25日
    瀏覽(22)
  • 讀數(shù)據(jù)壓縮入門筆記06_上下文轉(zhuǎn)換

    讀數(shù)據(jù)壓縮入門筆記06_上下文轉(zhuǎn)換

    3.3.1.1.?如果這兩個符號是相同的,那么行程繼續(xù) 3.3.1.2.?如果不相同,那么當(dāng)前行程終止 8.6.1.1.?真實數(shù)據(jù)中普遍存在 9.3.1.1.?事實上符號之間的順序很重要 9.3.4.1.?lexicographical permutation 9.3.4.2.?BWT會打亂數(shù)據(jù)流中符號的順序,并試圖讓相同的符號簇彼此靠近 9.3.4.3.?找出原始數(shù)

    2024年02月09日
    瀏覽(21)
  • pymysql 上下文管理器控制事務(wù)提交和回滾

    示例: 從上面例子看出, 在with結(jié)構(gòu)進入時,事務(wù)開始begin 在with結(jié)構(gòu)退出時,會根據(jù)是否產(chǎn)生異常進行commit和rollback操作,并關(guān)閉連接

    2024年01月25日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包