Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/181.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么上下文管理器在生成后关闭?_Python_Generator_Contextmanager - Fatal编程技术网

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

Python 为什么上下文管理器在生成后关闭?,python,generator,contextmanager,Python,Generator,Contextmanager,我试图生成一个上下文管理器,它是在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

我试图
生成一个上下文管理器,它是在
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
我在一个相关的主题上看到了,答案是关于对象被垃圾收集的时间——但是为什么
cm
在返回供调用方使用之前会被垃圾收集

编辑

当你写作的时候

foo_maker = make_foo()
foo = next(foo_maker)

然后CM并没有关闭——所以看起来CM确实是GC,因为生成器是GC。但是,既然它被返回并可能在之后使用,那么它不应该被单独保留吗?

我认为这是因为您的方法定义和您如何调用它

如果您不使用
foo=next(make\u 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

contxt管理器不是垃圾收集的,生成器对象是垃圾收集的,这
.close
将其删除,这将导致
with
语句执行
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。你为什么这么认为?你只调用了
next()
一次,所以
make\u foo()
产生后就再也没有恢复。因此,带
块从未有机会退出。这是一个有趣的问题。我要补充的是,在cpython中没有任何垃圾收集,而是ref计数。他们的意见不同。