手动实施 with block 会产生不同的东西

Implementing with block manually produces different things

假设我写

with some_method()
    ...

我的印象是 with 命令首先对 some_method() 返回的任何内容调用 __enter__() 方法。 (我相信 some_method() 返回的东西叫做 "context manager",这只是意味着它有方法叫做 __enter__()__exit__()。)

我尝试手动调用 __enter__(),但得到的结果与我预期的不同。这个具体示例是在 TensorFlow 的上下文中出现的,但我很确定它与 TensorFlow 本身没有任何关系。

import tensorflow as tf
x = tf.Session()
x.as_default().__enter__()
print(tf.get_default_session()) 

打印 None

import tensorflow as tf
tf.Session().as_default().__enter__()
print(tf.get_default_session()) 

打印 None,但

import tensorflow as tf
with tf.Session().as_default():
    print(tf.get_default_session()) 

打印 <tensorflow.python.client.session.Session object at 0x114217a90>

我发布了本质上相同的问题 here,但我犯了编辑它太多次的错误,直到最后它才不再问它开始时问的问题。所以我只是重新提出问题。

这可能是因为您放弃了上下文管理器。很少有上下文管理器设计为在 __enter__ 之后被丢弃而不调用 __exit__,如果您这样做,它们的行为可能无法预测。其中一些在收集垃圾时自动调用 __exit__ 的等价物,而另一些则以奇怪的方式运行。

在这种特殊情况下,我相信 tf.Session().as_default() 最终会委托给 generator-based context manager。底层生成器在垃圾收集时自动调用其close方法,这与调用上下文管理器的__exit__方法非常相似。