是否可以根据情况使用不同的上下文管理器执行单个块?
示例:
if some_condition:
with ContextManager(**args) as contex:
... # some block
else:
with OtherContextManager(**other_args) as contex:
... # the same block
一种方法是将...
包装到一个函数中,但这对我来说可能不太方便。还有另一种可能性吗?
答案 0 :(得分:4)
您可以将构造的对象存储在变量中,例如:
if some_condition:
cm = ContextManager(**args)
else:
cm = OtherContextManager(**other_args)
with cm as contex:
... # some block
以上内容可以轻松扩展到三个可能的上下文管理器等。您还可以决定例如在“输入”上下文之前先“修补”上下文管理器。
尽管通常会看到类似with foo() as bar:
的模式,但实际上Python只是对foo()
求值,获取该元素,然后在对象上调用.__enter__()
。该方法的结果存储在bar
中。
因此,foo()
调用没有任何“特殊”之处,您可以在左侧使用任何类型的对象。因此,您可以例如将if
-else
逻辑封装在一个单独的函数中,然后返回上下文管理器,然后使用该变量,或者将上下文管理器作为参数传递。只要您在with
语句中使用它,Python就会在幕后调用.__enter__(..)
和.__exit__(..)
。
答案 1 :(得分:2)
怎么样...
with ContextManager(**args) if some_condition else OtherContextManager(**other_args) as contex:
... # some block
...?
答案 2 :(得分:2)
我们可以发疯,利用__enter__
和__exit__
都是方法,并且在原始对象中调用它们(而不是{{1}返回的对象)这一事实}):
__enter__
并像这样使用它:
class WrapperContext:
def __init__(self, condition):
if condition:
self.real_context = ContextA()
else:
self.real_context = ContextB()
def __enter__(self):
return self.real_context.__enter__()
def __exit__(self):
return self.real_context.__exit__()