前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python上下文管理器

Python上下文管理器

作者头像
dongfanger
发布2021-12-10 11:47:54
3070
发布2021-12-10 11:47:54
举报
文章被收录于专栏:dongfanger

with语句会设置一个临时的上下文,交给上下文管理器对象控制,并且负责清理上下文。

比如在打开文件时通常都会使用with语句:

代码语言:javascript
复制
with open("a.txt") as f:
    f.read()

with块执行完后会自动关闭文件。

Python上下文管理器对象存在的目的就是管理with语句。

实现一个上下文管理器

上下文管理器协议包含__enter____exit__两个方法,所以要实现一个上下文管理器,就得实现这两个方法,比如:

代码语言:javascript
复制
class LookingGlass:

    def __enter__(self):
        import sys
        self.original_write = sys.stdout.write
        sys.stdout.write = self.reverse_write
        return 'JABBERWOCKY'

    def reverse_write(self, text):
        self.original_write(text[::-1])

    def __exit__(self, exc_type, exc_value, traceback):
        import sys
        sys.stdout.write = self.original_write
        if exc_type is ZeroDivisionError:
            print('Please DO NOT divide by zero!')
            return True
  • __enter__是上下文管理器的入口,在with语句开始运行时调用。
  • __exit__是上下文管理器的出口,在with语句运行结束后调用。

上下文管理器对象是在执行with后面的表达式得到的:

代码语言:javascript
复制
with LookingGlass() as what:
    print(what)

as子句是可选的,在as执行前就已经得到了上下文管理器对象,在as执行时实际就已经调用__enter__了。

把生成器变为上下文管理器

使用@contextmanager装饰器能减少创建上下文管理器的样板代码量,只需要实现一个有yield语句的生成器,生成想让__enter__方法返回的值。

示例:

代码语言:javascript
复制
import contextlib


@contextlib.contextmanager
def looking_glass():
    import sys
    original_write = sys.stdout.write

    def reverse_write(text):
        original_write(text[::-1])

    sys.stdout.write = reverse_write
    msg = ''
    try:
        yield 'JABBERWOCKY'
    except ZeroDivisionError:
        msg = 'Please DO NOT divide by zero!'
    finally:
        sys.stdout.write = original_write
        if msg:
            print(msg)

yield语句的作用是:

  • 在yield语句前面的代码在with块开始时执行,相当于__enter__
  • 在yield语句后面的代码在with块结束时执行,相当于__exit__

注意这里的yield与迭代没有任何关系,这其实引出了Python另一个重要技术点,协程:执行到某一点时暂停,让客户代码运行,直到客户让协程继续做事。下篇文章将展开对Python协程的学习。

参考资料: 《流畅的Python》第15章 上下文管理器和else块

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-12-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实现一个上下文管理器
  • 把生成器变为上下文管理器
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档