欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python 的 with 語(yǔ)句詳解

 更新時(shí)間:2014年06月13日 10:11:27   投稿:junjie  
這篇文章主要介紹了Python 的 with 語(yǔ)句,本文詳細(xì)講解了with語(yǔ)句、with語(yǔ)句的歷史、with語(yǔ)句的使用例子等,需要的朋友可以參考下

一、簡(jiǎn)介

with是從Python 2.5 引入的一個(gè)新的語(yǔ)法,更準(zhǔn)確的說,是一種上下文的管理協(xié)議,用于簡(jiǎn)化try…except…finally的處理流程。with通過__enter__方法初始化,然后在__exit__中做善后以及處理異常。對(duì)于一些需要預(yù)先設(shè)置,事后要清理的一些任務(wù),with提供了一種非常方便的表達(dá)。

with的基本語(yǔ)法如下,EXPR是一個(gè)任意表達(dá)式,VAR是一個(gè)單一的變量(可以是tuple),”as VAR”是可選的。

復(fù)制代碼 代碼如下:

with EXPR as VAR:
    BLOCK

根據(jù)PEP 343的解釋,with…as…會(huì)被翻譯成以下語(yǔ)句:
復(fù)制代碼 代碼如下:

mgr = (EXPR)
exit = type(mgr).__exit__  # Not calling it yet
value = type(mgr).__enter__(mgr)
exc = True
try:
    try:
        VAR = value  # Only if "as VAR" is present
        BLOCK
    except:
        # The exceptional case is handled here
        exc = False
        if not exit(mgr, *sys.exc_info()):
            raise
        # The exception is swallowed if exit() returns true
finally:
    # The normal and non-local-goto cases are handled here
    if exc:
        exit(mgr, None, None, None)

為什么這么復(fù)雜呢?注意finally中的代碼,需要BLOCK被執(zhí)行后才會(huì)執(zhí)行finally的清理工作,因?yàn)楫?dāng)EXPR執(zhí)行時(shí)拋出異常,訪問mgr.exit執(zhí)行就會(huì)報(bào)AttributeError的錯(cuò)誤。


二、實(shí)現(xiàn)方式

根據(jù)前面對(duì)with的翻譯可以看到,被with求值的對(duì)象必須有一個(gè)__enter__方法和一個(gè)__exit__方法。稍微看一個(gè)文件讀取的例子吧,注意在這里我們要解決2個(gè)問題:文件讀取異常,讀取完畢后關(guān)閉文件句柄。用try…except一般會(huì)這樣寫:

復(fù)制代碼 代碼如下:

f = open('/tmp/tmp.txt')
try:
    for line in f.readlines():
        print(line)
finally:
    f.close()

注意我們這里沒有處理文件打開失敗的IOError,上面的寫法可以正常工作,但是對(duì)于每個(gè)打開的文件,我們都要手動(dòng)關(guān)閉文件句柄。如果要使用with來實(shí)現(xiàn)上述功能,需要需要一個(gè)代理類:
復(fù)制代碼 代碼如下:

class opened(object):

    def __init__(self, name):
        self.handle = open(name)

    def __enter__(self):
        return self.handle

    def __exit__(self, type, value, trackback):
        self.handle.close()

with opened('/tmp/a.txt') as f:
    for line in f.readlines():
        print(line)


注意我們定了一個(gè)名字叫opened的輔助類,并實(shí)現(xiàn)了__enter__和__exit__方法,__enter__方法沒有參數(shù),__exit__方法的3個(gè)參數(shù),分別代表異常的類型、值、以及堆棧信息,如果沒有異常,3個(gè)入?yún)⒌闹刀紴镹one。

如果你不喜歡定義class,還可以用Python標(biāo)準(zhǔn)庫(kù)提供的contextlib來實(shí)現(xiàn):

復(fù)制代碼 代碼如下:

from contextlib import contextmanager

@contextmanager
def opened(name):
    f = open(name)
    try:
        yield f
    finally:
        f.close()

with opened('/tmp/a.txt') as f:
    for line in f.readlines():
        print(line)


使用contextmanager的函數(shù),yield只能返回一個(gè)參數(shù),而yield后面是處理清理工作的代碼。在我們讀取文件的例子中,就是關(guān)閉文件句柄。這里原理上和我們之前實(shí)現(xiàn)的類opened是相同的,有興趣的可以參考一下contextmanager的源代碼。

三、應(yīng)用場(chǎng)景

廢話了這么多,那么到底那些場(chǎng)景下該使用with,有沒有一些優(yōu)秀的例子?當(dāng)然啦,不然這篇文章意義何在。以下摘自PEP 343。

一個(gè)確保代碼執(zhí)行前加鎖,執(zhí)行后釋放鎖的模板:

復(fù)制代碼 代碼如下:

@contextmanager
    def locked(lock):
        lock.acquire()
        try:
            yield
        finally:
            lock.release()

    with locked(myLock):
        # Code here executes with myLock held.  The lock is
        # guaranteed to be released when the block is left (even
        # if via return or by an uncaught exception).


數(shù)據(jù)庫(kù)事務(wù)的提交和回滾:
復(fù)制代碼 代碼如下:

@contextmanager
        def transaction(db):
            db.begin()
            try:
                yield None
            except:
                db.rollback()
                raise
            else:
                db.commit()

重定向stdout:
復(fù)制代碼 代碼如下:

@contextmanager
def stdout_redirected(new_stdout):
    save_stdout = sys.stdout
    sys.stdout = new_stdout
    try:
        yield None
    finally:
        sys.stdout = save_stdout

with opened(filename, "w") as f:
    with stdout_redirected(f):
        print "Hello world"


注意上面的例子不是線程安全的,再多線程環(huán)境中要小心使用。


四、總結(jié)

with是對(duì)try…expect…finally語(yǔ)法的一種簡(jiǎn)化,并且提供了對(duì)于異常非常好的處理方式。在Python有2種方式來實(shí)現(xiàn)with語(yǔ)法:class-based和decorator-based,2種方式在原理上是等價(jià)的,可以根據(jù)具體場(chǎng)景自己選擇。

with最初起源于一種block…as…的語(yǔ)法,但是這種語(yǔ)法被很多人所唾棄,最后誕生了with,關(guān)于這段歷史依然可以去參考PEP-343和PEP-340

相關(guān)文章

  • 深入解析Python中的集合類型操作符

    深入解析Python中的集合類型操作符

    這篇文章主要介紹了深入解析Python中的集合類型操作符,是Python入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-08-08
  • python httpx的具體使用

    python httpx的具體使用

    本文主要介紹了python httpx的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Python requests及aiohttp速度對(duì)比代碼實(shí)例

    Python requests及aiohttp速度對(duì)比代碼實(shí)例

    這篇文章主要介紹了Python requests及aiohttp速度對(duì)比代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Python使用pyh生成HTML文檔的方法示例

    Python使用pyh生成HTML文檔的方法示例

    這篇文章主要介紹了Python使用pyh生成HTML文檔的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-03-03
  • 對(duì)numpy中數(shù)組轉(zhuǎn)置的求解以及向量?jī)?nèi)積計(jì)算方法

    對(duì)numpy中數(shù)組轉(zhuǎn)置的求解以及向量?jī)?nèi)積計(jì)算方法

    今天小編就為大家分享一篇對(duì)numpy中數(shù)組轉(zhuǎn)置的求解以及向量?jī)?nèi)積計(jì)算方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-10-10
  • Python常見字典內(nèi)建函數(shù)用法示例

    Python常見字典內(nèi)建函數(shù)用法示例

    這篇文章主要介紹了Python常見字典內(nèi)建函數(shù)用法,結(jié)合具體實(shí)例形式分析了Python字典內(nèi)建函數(shù)實(shí)現(xiàn)針對(duì)字典的長(zhǎng)度、hash運(yùn)算、鍵值對(duì)遍歷、獲取、計(jì)算等相關(guān)操作技巧,需要的朋友可以參考下
    2018-05-05
  • Python實(shí)現(xiàn)的單向循環(huán)鏈表功能示例

    Python實(shí)現(xiàn)的單向循環(huán)鏈表功能示例

    這篇文章主要介紹了Python實(shí)現(xiàn)的單向循環(huán)鏈表功能,簡(jiǎn)單描述了單向循環(huán)鏈表的概念、原理并結(jié)合實(shí)例形式分析了Python定義與使用單向循環(huán)鏈表的相關(guān)操作技巧,需要的朋友可以參考下
    2017-11-11
  • Python使用turtle庫(kù)繪制科赫雪花詳細(xì)代碼

    Python使用turtle庫(kù)繪制科赫雪花詳細(xì)代碼

    科赫曲線是一種分形,其形態(tài)非常像雪花,因此又被稱作科赫雪花、雪花曲線,這篇文章主要給大家介紹了關(guān)于Python使用turtle庫(kù)繪制科赫雪花的相關(guān)資料,需要的朋友可以參考下
    2024-05-05
  • 分析PyTorch?Dataloader報(bào)錯(cuò)ValueError:num_samples的另一種可能原因

    分析PyTorch?Dataloader報(bào)錯(cuò)ValueError:num_samples的另一種可能原因

    這篇文章主要介紹了分析PyTorch?Dataloader報(bào)錯(cuò)ValueError:num_samples的另一種可能原因,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • Python的圖像處理庫(kù)Pillow安裝與使用教程

    Python的圖像處理庫(kù)Pillow安裝與使用教程

    Pillow庫(kù)是Python中用于圖像處理的開源庫(kù),提供了豐富的圖像處理功能,如圖像讀取、保存、裁剪、調(diào)整大小、旋轉(zhuǎn)、添加文字等,這篇文章主要給大家介紹了關(guān)于Python的圖像處理庫(kù)Pillow安裝與使用的相關(guān)資料,需要的朋友可以參考下
    2024-04-04

最新評(píng)論