亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

PyTips 0x0d - Python 上下文管理器

yuxue / 3610人閱讀

摘要:項目地址引入了語句與上下文管理器類型,其主要作用包括保存重置各種全局狀態(tài),鎖住或解鎖資源,關(guān)閉打開的文件等。了解了語句的執(zhí)行過程,我們可以編寫自己的上下文管理器。生成器的寫法更簡潔,適合快速生成一個簡單的上下文管理器。

項目地址:https://git.io/pytips

Python 2.5 引入了 with 語句(PEP 343)與上下文管理器類型(Context Manager Types),其主要作用包括:

保存、重置各種全局狀態(tài),鎖住或解鎖資源,關(guān)閉打開的文件等。With Statement Context Managers

一種最普遍的用法是對文件的操作:

with open("utf8.txt", "r") as f:
    print(f.read())
你好,世界!

上面的例子也可以用 try...finally... 實現(xiàn),它們的效果是相同(或者說上下文管理器就是封裝、簡化了錯誤捕捉的過程):

try:
    f = open("utf8.txt", "r")
    print(f.read())
finally:
    f.close()
你好,世界!

除了文件對象之外,我們也可以自己創(chuàng)建上下文管理器,與 0x01 中介紹的迭代器類似,只要定義了 __enter__()__exit__() 方法就成為了上下文管理器類型。with 語句的執(zhí)行過程如下:

執(zhí)行 with 后的語句獲取上下文管理器,例如 open("utf8.txt", "r") 就是返回一個 file object;

加載 __exit__() 方法備用;

執(zhí)行 __enter__(),該方法的返回值將傳遞給 as 后的變量(如果有的話);

執(zhí)行 with 語法塊的子句;

執(zhí)行 __exit__() 方法,如果 with 語法塊子句中出現(xiàn)異常,將會傳遞 type, value, traceback__exit__(),否則將默認為 None;如果 __exit__() 方法返回 False,將會拋出異常給外層處理;如果返回 True,則忽略異常。

了解了 with 語句的執(zhí)行過程,我們可以編寫自己的上下文管理器。假設(shè)我們需要一個引用計數(shù)器,而出于某些特殊的原因需要多個計數(shù)器共享全局狀態(tài)并且可以相互影響,而且在計數(shù)器使用完畢之后需要恢復(fù)初始的全局狀態(tài):

_G = {"counter": 99, "user": "admin"}

class Refs():
    def __init__(self, name = None):
        self.name = name
        self._G = _G
        self.init = self._G["counter"]
    def __enter__(self):
        return self
    def __exit__(self, *args):
        self._G["counter"] = self.init
        return False
    def acc(self, n = 1):
        self._G["counter"] += n
    def dec(self, n = 1):
        self._G["counter"] -= n
    def __str__(self):
        return "COUNTER #{name}: {counter}".format(**self._G, name=self.name)
        
with Refs("ref1") as ref1, Refs("ref2") as ref2: # Python 3.1 加入了多個并列上下文管理器
    for _ in range(3):
        ref1.dec()
        print(ref1)
        ref2.acc(2)
        print(ref2)
print(_G)
COUNTER #ref1: 98
COUNTER #ref2: 100
COUNTER #ref1: 99
COUNTER #ref2: 101
COUNTER #ref1: 100
COUNTER #ref2: 102
{"user": "admin", "counter": 99}

上面的例子很別扭但是可以很好地說明 with 語句的執(zhí)行順序,只是每次定義兩個方法看起來并不是很簡潔,一如既往地,Python 提供了 @contextlib.contextmanager + generator 的方式來簡化這一過程(正如 0x01 中 yield 簡化迭代器一樣):

from contextlib import contextmanager as cm
_G = {"counter": 99, "user": "admin"}

@cm
def ref():
    counter = _G["counter"]
    yield _G
    _G["counter"] = counter

with ref() as r1, ref() as r2:
    for _ in range(3):
        r1["counter"] -= 1
        print("COUNTER #ref1: {}".format(_G["counter"]))
        r2["counter"] += 2
        print("COUNTER #ref2: {}".format(_G["counter"]))
print("*"*20)
print(_G)
COUNTER #ref1: 98
COUNTER #ref2: 100
COUNTER #ref1: 99
COUNTER #ref2: 101
COUNTER #ref1: 100
COUNTER #ref2: 102
********************
{"user": "admin", "counter": 99}

這里對生成器的要求是必須只能返回一個值(只有一次 yield),返回的值相當于 __enter__() 的返回值;而 yield 后的語句相當于 __exit__()。

生成器的寫法更簡潔,適合快速生成一個簡單的上下文管理器。

除了上面兩種方式,Python 3.2 中新增了 contextlib.ContextDecorator,可以允許我們自己在 class 層面定義新的”上下文管理修飾器“,有興趣可以到官方文檔查看。至少在我目前看來好像并沒有帶來更多方便(除了可以省掉一層縮進之外:()。

上下文管理器的概念與修飾器有很多相似之處,但是要記住的是 with 語句的目的是為了更優(yōu)雅地收拾殘局而不是替代 try...finally...,畢竟在 The Zen of Python 中,

Explicit is better than implicit.

Simple is better than complex.

更重要:P。


歡迎關(guān)注公眾號 PyHub!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/37820.html

相關(guān)文章

  • PyTips 0x0f - Python 修飾與 functools

    項目地址:https://git.io/pytips Python 的修飾器是一種語法糖(Syntactic Sugar),也就是說: @decorator @wrap def func(): pass 是下面語法的一種簡寫: def func(): pass func = decorator(wrap(func)) 關(guān)于修飾器的兩個主要問題: 修飾器用來修飾誰 誰可以作為修飾器...

    dingding199389 評論0 收藏0
  • PyTips 0x 12 - Python 線程與協(xié)程(1)

    摘要:中關(guān)于線程的標準庫是,之前在版本中的在之后更名為,無論是還是都應(yīng)該盡量避免使用較為底層的而應(yīng)該使用。而與線程相比,協(xié)程尤其是結(jié)合事件循環(huán)無論在編程模型還是語法上,看起來都是非常友好的單線程同步過程。 項目地址:https://git.io/pytips 要說到線程(Thread)與協(xié)程(Coroutine)似乎總是需要從并行(Parallelism)與并發(fā)(Concurrency)談起...

    el09xccxy 評論0 收藏0
  • PyTips 0x01 - 迭代與生成

    摘要:項目地址迭代器與生成器迭代器與生成器是中比較常用又很容易混淆的兩個概念,今天就把它們梳理一遍,并舉一些常用的例子。生成器前面說到創(chuàng)建迭代器有種方法,其中第三種就是生成器。 項目地址:https://git.io/pytips 迭代器與生成器 迭代器(iterator)與生成器(generator)是 Python 中比較常用又很容易混淆的兩個概念,今天就把它們梳理一遍,并舉一些常用的例...

    chemzqm 評論0 收藏0
  • PyTips 0x16 - Python 迭代工具

    摘要:借鑒了中的某些迭代器的構(gòu)造方法,并在中實現(xiàn)該模塊是通過實現(xiàn),源代碼。 項目地址:https://git.io/pytips 0x01 介紹了迭代器的概念,即定義了 __iter__() 和 __next__() 方法的對象,或者通過 yield 簡化定義的可迭代對象,而在一些函數(shù)式編程語言(見 0x02 Python 中的函數(shù)式編程)中,類似的迭代器常被用于產(chǎn)生特定格式的列表(或序列)...

    mayaohua 評論0 收藏0
  • PyTips 0x04 - Python 閉包與作用域

    摘要:項目地址閉包在計算機科學中,閉包英語,又稱詞法閉包或函數(shù)閉包,是引用了自由變量的函數(shù)。這個被引用的自由變量將和這個函數(shù)一同存在,即使已經(jīng)離開了創(chuàng)造它的環(huán)境也不例外。 項目地址:https://git.io/pytips 閉包(Closure) 在計算機科學中,閉包(英語:Closure),又稱詞法閉包(Lexical Closure)或函數(shù)閉包(function closures),是...

    leejan97 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<