python--context上下文管理器

上下文管理器

語法

with EXPR as VAR:
    BLOCK

概念

1. 上下文表達(dá)式:with open('hello.txt') as f:
2. 上下文管理器:open('hello.txt')
3. f 不是上下文管理器,是資源對象
為什么要用上下文管理器?

1.可以以一種更加優(yōu)雅的方式,操作(創(chuàng)建/獲取/釋放)資源,如文件操作、數(shù)據(jù)庫連接;
2.可以以一種更加優(yōu)雅的方式,處理異常;

如何實(shí)現(xiàn)上下文管理器

實(shí)現(xiàn)這樣一個上下文管理,要先知道上下文管理協(xié)議。
簡單點(diǎn)說,就是在一個類里,實(shí)現(xiàn)了enterexit的方法,這個類的實(shí)例就是一個上下文管理器。

示例

class Resource():
    def __enter__(self):
        print('===connect to resource===')
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('===close resource connection===')
        
    def operate(self):
        print('===in operation===')
        
with Resource() as res:
    res.operate()

輸出

===connect to resource===
===in operation===
===close resource connection===

在編寫上下文管理器時,需要將資源的連接或者獲取放在enter中,而將資源的關(guān)閉寫在exit

使用contextlib

編寫enterexit仍然很繁瑣,因此Python的標(biāo)準(zhǔn)庫contextlib提供了更簡單的寫法,上面的代碼可以改寫如下:

from contextlib import contextmanager

class Resource():   
    def operate(self):
        print('===in operation===')

@contextmanager
def create_resource():
    print('Begin')
    q = Resource()
    yield q
    print('End')

with create_resource() as f:
    f.operate()

很多時候,我們希望在某段代碼執(zhí)行前后自動執(zhí)行特定代碼,也可以用@contextmanager實(shí)現(xiàn)

@contextmanager
def tag(name):
    print("<%s>" % name)
    yield
    print("</%s>" % name)

with tag("h1"):
    print("hello")
    print("world")

輸出

<h1>
hello
world
</h1>

1.with語句首先執(zhí)行yield之前的語句,因此打印出<h1>;
2.yield調(diào)用會執(zhí)行with語句內(nèi)部的所有語句,因此打印出hello和world;
3.最后執(zhí)行yield之后的語句,打印出</h1>。

@closing

如果一個對象沒有實(shí)現(xiàn)上下文,我們就不能把它用于with語句。這個時候,可以用closing()來把該對象變?yōu)樯舷挛膶ο?。例如,用with語句使用urlopen():

from contextlib import closing
from urllib.request import urlopen

with closing(urlopen('https://www.python.org')) as page:
    for line in page:
        print(line)

closing也是一個經(jīng)過@contextmanager裝飾的generator,它的作用就是把任意對象變?yōu)樯舷挛膶ο?,并支持with語句,這個generator編寫起來其實(shí)非常簡單:

@contextmanager
def closing(thing):
    try:
        yield thing
    finally:
        thing.close()

本文采納以下文章部分內(nèi)容:

https://www.cnblogs.com/wongbingming/p/10519553.html

https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001478651770626de401ff1c0d94f379774cabd842222ff000

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容