亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python中的上下文管理器

系統 1563 0

Python中的上下文管理器,實際上就是實現了上下文管理協議的對象。在Python中打開文件的時候,我們需要確保文件被使用完畢之后,對其進行關閉操作——調用文件對象的close()方法。如果不使用上下文管理器,經典的處理方式就是將close()方法的調用放在一個finally語句中:

            
              f = open("www.log")

try:
    print("do something with file")
finally:
    f.close()
            
          

?這里finally的唯一作用就是確保文件對象最后被正確關閉,為此我們使用了一個try...finally語句塊——這就需要我們在實現業務邏輯的時候,去考慮一些業務邏輯之外的東西,我們需要一個類似于自動內存回收(GC)的機制,來自動地幫我們做文件描述符的清理,讓我們把精力都用在業務邏輯實現上。上下文管理器就可以達到這樣的目的。而Python的文件對象是實現了這個協議了的:

            
              with open("www.log") as f:
    print("do something with file")
            
          

這和上面的try...finally風格的代碼實現了等價的功能,只不過這里的代碼更加簡潔了,文件對象最后也可以被關閉。

上下文管理協議的定義非常簡單,就是在被上下文包覆的代碼執行前執行一個__enter__方法;在被包覆代碼之后執行一個__exit__方法,根據這個定義我們就能寫出一個非常簡單的上下文管理器:

            
              class SimpleContext:
    def __enter__(self):
        print("before code block")

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("after code block")


if __name__ == '__main__':
    with SimpleContext():
        print("I am code block")
            
          

運行這個代碼的輸出為:

            
              before code block
I am code block
after code block

            
          

可以看到,with塊下的代碼執行之前,運行了上下文協議的__enter__方法,with塊下的代碼執行之后,運行了上下文協議的__exit__ 方法。

可以通過在__enter__方法中返回一個值,將此值定義應用在with塊中,可以通過as關鍵詞來獲取對這個值的引用,這就是上面看到的with open("www.log") as f中獲取對f引用的方法:

            
              class SimpleContext:
    def __enter__(self):
        print("before code block")
        return 100

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("after code block")


if __name__ == '__main__':
    with SimpleContext() as sc:
        print(sc)
        print("I am code block")
            
          

這樣輸出就變成了:

            
              before code block
100
I am code block
after code block
            
          

另外可以通過__exit__方法的回調參數exc_type, exc_val, exc_tb來訪問with語句塊的代碼執行的異常信息,如果代碼塊一切正常,它們都是None;如果有異常拋出,就可以通過這三個參數來獲取異常信息,做相應的處理。

以上就是上下文管理器的一個完整的內容了。但是Python中,為了讓實現上下文管理器的過程更加簡單,提供了另一種實現上下文協議的方法,就是通過contextlib模塊中的contextmanager裝飾器,結合使用生成器來實現:

            
              import contextlib

@contextlib.contextmanager
def SimpleContext():
    print("before code block")
    try:
        yield 100
    except Exception as e:
        print("handle e here, not in __exit__")
    finally:
        print("after code block")


if __name__ == '__main__':
    with SimpleContext() as sc:
        print(sc)
        print("I am code block")
            
          

這個實現的輸出和上面的輸出是一致的,只是寫法的不同。第一種寫法結構上更加清晰,第二種寫法邏輯上更加連續,哪一種方法更好,作出自己的選擇即可。

以上。


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 久久精品加勒比中文字幕 | 四虎影院新网址 | 亚洲黄色在线观看视频 | 香蕉亚洲 | 亚洲成a| 国产91精品系列在线观看 | 麻豆传煤一区免费入 | 日韩在线看片 | 国产免费不卡v片在线观看 国产免费不卡视频 | 青青久草在线 | 99热久久精品国产 | 99热成人精品国产免男男 | 性久久久久久久久久 | 999国内精品永久免费视频 | 久久综合九色综合亚洲 | 97av在线| 久久国产精品岛国搬运工 | 在线观看日本免费不卡 | 午夜在线精品不卡国产 | 欧美视频在线一区 | 天天透天天狠 | 高清国产一区二区 | 亚洲午夜一区二区三区 | 久久天天躁狠狠躁夜夜中文字幕 | 欧洲一级做a爱在线观看 | 亚州激情视频在线播放 | 国产成人精品一区二区免费 | 天天拍夜夜拍 | 亚洲一区二区三区首页 | 国产免费高清视频 | 香蕉国产 | 久久综合图区亚洲综合图区 | 欧美成人一区二区三区不卡视频 | 色婷婷5月精品久久久久 | 国产精品一区二区手机看片 | 久草视频免费播放 | 国产成人精品在线 | 四虎国产精品永久地址99 | 5x性区m免费毛片视频看看 | 日韩特级毛片 | 日韩精品一区二区三区四区 |