在`with expression as variable`中赋值给`variable`的是什么?

时间:2017-09-14 17:32:39

标签: python python-3.x

从学习Python:

  

with语句的基本格式如下所示   方括号中的可选部分:

with expression [as variable]:
    with-block
     

假设此处expression返回支持该对象的对象   上下文管理协议(稍后将详细介绍此协议)。   如果存在可选的as子句,则此对象还可以返回将分配给名称variable的值。

     

请注意, variable未必分配结果   expression ; expression的结果是对象   支持上下文协议,可以分配 variable   打算在声明中使用的其他内容。

expression被评估为上下文管理器对象。

分配给variable的内容是什么?引用只表示它不是上下文管理器对象。

variable的赋值是否调用上下文管理器类的某个方法来生成分配给variable的实际值?

感谢。

2 个答案:

答案 0 :(得分:10)

__enter__返回的是什么。来自documentation on the __enter__ method of context managers

  

contextmanager.__enter__()

     

输入运行时上下文并返回此对象或与运行时上下文相关的其他对象。 此方法返回的值使用此上下文管理器绑定到as语句的with子句中的标识符。

(强调我的)

调用__enter__的结果很可能是一个上下文管理器,规范中没有任何内容禁止这样做。它当然可以是与运行时上下文相关的另一个对象,如文档所述。

__enter__返回的对象可以一次又一次地用作上下文管理器。 file objects,例如:

with open('test_file') as f1:   # file.__enter__ returns self
    with f1 as f2:                # use it again, get __self__ back
        print("Super context managing")
        with f2 as f3, f1 as f4:   # getting weird.
            print("This can go on since f1.__enter__ returns f1")
        print("f1.__exit__ has been called here, though :)")
        print("f1 closed: {}".format(f1.closed))

并不是说前面的内容很有意义,只是为了说清楚。

答案 1 :(得分:9)

如果provides both __enter__ and __exit__,您的对象可以充当上下文管理器。 __enter__返回的对象绑定到您在as语句的with部分中指定的对象:

In [1]: class Foo:
   ...:     def __enter__(self):
   ...:         return 'hello'
   ...:     def __exit__(self, *args):
   ...:         pass
   ...:

In [2]: with Foo() as a:
   ...:     print(a)
   ...:
hello