上下文管理器

  • 是一个对象
  • 这个对象有两个特殊的方法 __enter__() 和 __exit__()
  • 通过 with 语句调用这个对象时,能自动执行两个特殊方法进入和退出对象,代码非常简洁、方便
  • 一般这样写:with 对象 as 标识符:

1、首先得了解一下异常处理

前面文章讲解过,详细可以点击【异常处理的四种方法,不只是try】文章

异常 try

try:    f = open('file.txt', 'r')    print(f.read())  # 返回:文本内容finally:    f.close()

2、with 语句:可以替代 try ... finally ... 语句,使代码更简洁

用 with 语句代替 try 的写法

with open('file.txt', 'r') as f:    print(f.read())  # 返回:文本内容

说 with 语句执行过程前,需要了解两个类的特殊方法,详细了解可点击【类的特殊方法,自动调用】

特殊方法说明

  • 以下两个方法只能同时使用,只用做 with 语句才会自动调用
  • 自动调用,无需我们自己编写

特殊方法理解

  • __enter__:此方法的返回值是上下文管理器对象,会绑定到 as 子句中的标识符 f
  • __exit__:关闭上下文管理器对象,需不需要抛出错误,由返回值决定

说一下 with语句 的执行过程

程序遇到 with 就判定后面是一个上下文管理器

此例中打开 file.txt 文件作为一个上下文管理器对象

  1. 对 open('file.txt', 'r', encoding='utf8') 求值,获得一个上下文管理器对象
  2. 调用上下文管理器的 __enter__ 方法,并把对象赋值给 as 子句中的标识符 f
  3. 执行语句块 print(f.read())
  4. 调用上下文管理器的 __exit__ 方法,关闭上下文管理器对象 f

3、自定义上下文管理器-通过类来实现

需要在类中自定义手动实现 __enter__ 和 __exit__ 方法

__enter__() 定义方法:返回self(对象本身),不返回无法执行 drink 方法;返回其他对象,执行其他对象的方法

__exit__() 定义方法:不返回 ,程序会正常报代码错误;返回 False,程序会正常报代码错误;返回 True,程序会忽略代码错误

下面看三个示例

示例一:__exit__()不返回值




python 自定义类实现with python调用自定义类_python exit()什么意思

代码正常报错



示例二:__exit__()返回值 False




python 自定义类实现with python调用自定义类_pyhton=实现调用自定义模块_02

代码正常报错



示例三:__exit__()返回值 True




python 自定义类实现with python调用自定义类_python exit()什么意思_03

代码不报错



总结:自定义上下文管理器,类的实现方式

  • __enter__() 方法,必须返回 self或者其他对象,不返回的话 with ... as f: f 的值为 None,f 无法执行对象方法,就没有什么意义了
  • __exit__() 方法,不返回值,对于代码报错,程序会自动报错
  • __exit__() 方法,返回 False,对于代码报错,程序会自动报错
  • __exit__() 方法,返回 True,对于代码报错,程序不报错,正常执行,所以返回 True 时要特别注意

4、自定义上下文管理器-通过函数来实现

需要用装饰器和生成器函数

两种情况:finally中没有 return;finally中有 return

from contextlib import contextmanager  # python内置模块

示例一:contextlib装饰器,finally 中不返回




python 自定义类实现with python调用自定义类_pyhton=实现调用自定义模块_04


示例二:contextlib装饰器,finally 中返回 True、False、空、其他


python 自定义类实现with python调用自定义类_pyhton=实现调用自定义模块_05

代码不报错


总结:自定义上下文管理器,函数的实现方式

  • 需要 contextmanager 装饰器
  • 需要一个生成器,yield 返回对象
  • yield 要用try ... finally 语句包裹,不然对象报错,后面不执行
  • finally 语句不返回值,代码正常报错
  • finally 语句有返回,代码不报错

喜欢的小伙伴,请关注 python一看便懂。