![ef23147395a8e584048e02a5953be5fc.png](https://img-blog.csdnimg.cn/img_convert/ef23147395a8e584048e02a5953be5fc.png)
开张名义:上下文管理器是一个对象.用在 with 语句中,开始用调用这个对象的 __enter__ 方法,结束会自动调用这个对象的 __exit_ 方法.另外在 with ... as ... 中,as 的返回值便是 __enter__ 方法的返回值.可以有返回值,可以没有返回值(None).
示例1
# 这个例子来自<Fluent Python>
# 新建一个类,用它的实例作为上下文选择器
class LookingGlass:
"""在此创造的上下文中,标准输出为反向输出"""
def __enter__(self):
import sys
self.original_write = sys.stdout.write # 保存标准输出
sys.stdout.write = self.reverse_write # 将本来的标准输出转化为反向输出
return 'HAW' #返回值,如果有as的话,这个便是as后变量的值
def reverse_write(self, text):
self.original_write(text[::-1])
def __exit__(self, exc_type, exc_value, traceback):#依次为异常类/异常实例/traceback对象
import sys
sys.stdout.write = self.original_write # 退出上下文前,恢复原来的标准输出
if exc_type is ZeroDivisionError:
print("Don't Do Not Divide by 0")
return True
# 开始试验
with LookingGlass() as what:
print('alice, you are ok')
print(what)
# 没在上下文中
print('alice, you are ok')
print(what)
#-----------输出结果----------------#
# ko era uoy ,ecila
# WAH
# alice, you are ok
# HAW
with 语句方便了调用 __enter__/__exit__ .也就是说我们可以在不使用 with 的前提下手动调用这两个方法.
示例2
manager = LookingGlass() # 创建上下文管理实例
manager
# <__main__.LookingGlass at 0x7f0764641208>
manager.__enter__() # 开始进入上下文
# WAH
print('I Like')
# ekiL Io
manager.__exit__(None, None, None)
当我们调用 __enter_ 的时候,丢掉了它的返回值.这没关系,照样会进入上下文.
小结:上下文管理器就是一个对象,在开始自动调用__enter__ , 在结束自动调用 __exit__ 比较特殊的是,使用 open() 打开文件的时候,这个上下文管理器调用自身的 __enter__ 会返回自身, 即文件句柄. 所以当我们使用 with open... 的时候,必须要有 as 语句.