没有Yield的Context Manager

sha*_*l85 8 python contextmanager

我是否可以拥有一个偶尔不会产生的上下文管理器,在这种情况下,with语句中的代码根本不会被执行?

import contextlib

@contextlib.contextmanager
def MayNotYield(to_yield):
  if to_yield:
    yield

with MayNotYield(True):  
  print 'This works.'

with MayNotYield(False):  
  print 'This errors.'
Run Code Online (Sandbox Code Playgroud)

我可以要求用户使用try-catch包装with语句,但这不是首选.我也可以做以下但它也很难看.

import contextlib

@contextlib.contextmanager
def AlwaysYields(to_yield):
  if to_yield:
    yield 1
  else:
    yield 2

with AlwaysYields(True) as result:
  if result == 1:
    print 'This works.'
Run Code Online (Sandbox Code Playgroud)

dma*_*ttp 6

另一种选择是只使用常规生成器而不是上下文管理器;普通的发电机不会有这个限制。但是您必须将它与“for”构造一起使用,而不是使用“with”:

def MayNotYield(to_yield):
   if to_yield:
      yield

for _ in MayNotYield(True):
   print('This prints.')

for _ in MayNotYield(False):
   print('This does not.')
Run Code Online (Sandbox Code Playgroud)


Blc*_*ght 5

不幸的是,上下文管理器协议没有给上下文管理器一个说"不要运行with块"的方法(除了引发异常__enter__).如果您正在使用上下文管理器,我认为您的第二种方法是__enter__返回一个值来表示是否应该运行该块是最好的方法.如果由于某些其他原因不需要上下文管理器,则可以使用简单的if语句:

if do_stuff:
    # do the stuff
Run Code Online (Sandbox Code Playgroud)