斷裂:Python的3.7將專門爲這個原因(commit)提供nullcontext
。我將在可用時更新鏈接到文檔。
對於3.7之前的Python版本:標準庫不提供專門爲這些用例設計的上下文管理器。
然而,事實證明,contextlib.suppress
(自3.4版本)可用於在第一種情況下該目的,即當沒有as
子句:
ctx_mgr = <meaningfulContextManager> if <condition> else contextlib.suppress()
with ctx_mgr:
...
因爲Python 3.3,類似的工作 - 周圍也是可用的,contextlib.ExitStack
,儘管比suppress
慢(這在我的測試中需要兩倍的時間)。
如果您需要as
子句,或者在使用3.3以前的Python版本時,開發人員需要自行開發。 這裏是一個可能的實現(見注在底部,但所有的錯誤都是我的):
class NullContextManager(object):
def __init__(self, dummy_resource=None):
self.dummy_resource = dummy_resource
def __enter__(self):
return self.dummy_resource
def __exit__(self, *args):
pass
人們可以接着寫:
ctx_mgr = <meaningfulContextManager> if <condition> else NullContextManager(dummy_resource)
with ctx_mgr as resource:
<operations on resource>
當然,dummy_resource
需要支持要求的所有操作的「有意義」的資源。因此,例如,如果有意義的上下文管理器__enter__()
返回的是在託管塊內返回quack()
的內容,則dummy_resource
也需要支持該操作,儘管可能完全沒有任何操作。
class DummyDuck(object):
def quack()
# Ssssh...
pass
ctx_mgr = <meaningfulContextManager> if <condition> else NullContextManager(DummyDuck())
with ctx_mgr as someDuck:
someDuck.quack()
來源:A Python feature request。非常感謝那些爲這次討論做出貢獻的人。這是我在一個自我回答的問題中總結其結果的嘗試,以節省人們閱讀那條冗長的線索的時間。另請參閱Python文檔中提到的this use of ExitStack
。
如果'if 1:'替代''with whatever:''? – Alfe