簡體   English   中英

為什么生成器不是上下文管理器?

[英]Why are generators not context managers?

生成器有可能管理資源,例如通過從上下文管理器內部yield 調用生成器的close()方法(或引發異常close()立即釋放資源。

由於很容易忘記最后調用close() ,因此我認為很明顯也為此使用上下文管理器(並處理潛在的異常)。 我知道我可以為此使用contextlib.closing ,但是在with語句中直接使用生成器會更好嗎?

生成器應該是上下文管理器嗎?

通常,您沒有看到更多生成器作為上下文管理器,反之亦然,原因是它們旨在解決不同的問題。 上下文管理器之所以出現,是因為它提供了一種簡潔明了的方式來將可執行代碼限定於資源。

有一個很好的理由,您可能希望將實現__iter__()與作為上下文管理器的“單一職責原則”分開。 單一責任歸結為概念

讓班上一件事做好

列表是可迭代的,但這是因為它們是一個集合。 他們除了所擁有的東西外,不管理其他任何狀態,而迭代只是訪問該狀態的另一種方式。 除非您需要使用迭代作為訪問包含對象狀態的一種方式,否則我看不出將兩者混合並匹配的理由。 即使那樣,我也會竭盡全力以真正的OO風格將其分開。

就像Wheaties所說的那樣,您希望讓班級只做“一件事情,並且做得很好”。 特別是對於上下文管理器,他們正在管理上下文。 所以問問自己,這里的背景是什么? 大多數情況下,它將打開一個資源。 前一陣子我問過要與上下文管理器一起使用隊列 ,而響應基本上是,隊列作為上下文沒有意義。 但是,“處於任務中”是我所處的真實上下文,因此為此創建上下文管理器是有意義的。

此外,沒有迭代with語句。 例如,我無法打開文件並在一條語句中進行如下遍歷:

for line in file with open(filename) as file:
    ...

必須分兩行完成:

with open(filename) as file:
    for line in file:
        ...

這很好,因為所管理的上下文不是“我們正在遍歷文件”,而是“我們有一個打開的文件”。 再說一遍, 背景是什么? 你到底在做什么 最有可能的是,您的托管上下文實際上並不是資源的迭代。 但是,如果您查看特定的問題,則可能會發現確實存在生成器正在管理上下文的情況。 希望了解上下文的真正含義將為您提供一些有關如何適當管理上下文的想法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM