为什么上下文管理器在产生后关闭?

Why is the context manager closed after it is yielded?

我正在尝试 yieldwith 语句中创建的上下文管理器。然而,我不明白的事情发生了:上下文管理器在它被产生之前关闭,即使生成器中的执行没有退出 with 的范围。例如:

class CM:
  def __enter__(self):
    print('enter cm')
    return self
  def __exit__(self, exc_type, exc_val, exc_tb):
    print('exit cm')


def make_foo():
  with CM() as cm:
    print('before yield')
    yield cm
  print('after yield')


print('before make_foo')
foo = next(make_foo())
print('after make_foo')

产出

before make_foo
enter cm
before yield
exit cm
after make_foo

我在相关主题上看到了 this thread,答案是关于对象被垃圾回收的时间——但是为什么 cm 在返回供使用之前被垃圾回收来电者是?

编辑

改写时

foo_maker = make_foo()
foo = next(foo_maker)

那么CM并没有关闭——所以看来CM确实是GC了,因为generator是GC。但它不应该单独留下,因为它会被退回并可能在之后使用吗?

我认为这是因为您的方法定义和调用方式。

如果你不是 foo = next(make_foo()) 使用这个 :

for i in make_foo():
  print('thanks I saw cm')

结果是这样的:

enter cm
before yield
thanks I saw cm
exit cm
after yield
after make_foo