上下文管理器和with块

文章目录


前言

相信很多小伙伴在对文件操作,或者锁的操作时会经常用到with语句,因为使用它给我们带来了极大的便利,比如在文件操作中,使用它,你再也不用担心你的文件在使用完成后没有关闭;在锁的操作,你也再也不用担心开了一把锁而忘记关闭造成死锁等现象...总之,它会给你做好一切“善后”的事情哈哈哈哈(这个比喻可能不是那么恰当)

一、上下文管理器是什么?

上下文管理器对象存在的目的是管理with语句,就像迭代器的存在是为了管理for语句一样。

它包含两个协议:__enter__和__exit__方法。with语句开始时,会在上下文中调用__enter__方法,with语句结束后,会调用__exit__方法。

二、使用步骤

这里列出两个实例,两个栗子的目的都是为了在控制中镜像输出。

1.上下文管理器的实现方案一

# 实现一个镜像输出
import sys
class MirrorOutput:

    def __enter__(self):
        self.output = sys.stdout.write  # 定义一个变量用来接受系统的输出方法
        sys.stdout.write = self.__reverse_output__  # 将系统的输出方法改为自己定义的输出方法

    def __reverse_output__(self, text):
        return self.output(text[::-1])

    def __exit__(self, exc_type, exc_val, exc_tb):
        sys.stdout.write = self.output  # 退出上下文后将系统的输出方法还原


if __name__ == '__main__':
    with MirrorOutput() as mo:
        print('好好学习,天天向上!')

    print('好好学习,天天向上!')

根据with语句的执行步骤,我们只要实现__enter__和__exit__方法,就可以实现一个上下文管理器。

在__enter__中,我们定义一个变量用来保系统的输出方法,同时将系统的输出方法改为我们自己的定义的输出方法(镜像输出),这样,在with语句内部,只要是在控制台输出的内容,都是镜像的。

在__exit__中,我们将系统的输出方法还原为它原有的方法,保证系统的正确性。在with语句以外的输出方法就是正常的了。

2.上下文管理器的实现方案二

import sys
from contextlib import contextmanager


# 还是实现一个镜像输出
class MirrorOutput:

    @contextmanager
    def mirror_output(self):

        self.output = sys.stdout.write

        def reverse_output(text):
            return self.output(text[::-1])

        sys.stdout.write = reverse_output

        # 分界线以上的作用类似于__enter__方法
        yield "这里是分界线"  # yield产出的值会绑定在as字句的目标变量上
        # 分界线以下的作用类似于__exit__方法
        sys.stdout.write = self.output


if __name__ == '__main__':
    with MirrorOutput().mirror_output() as mo:
        print('好好学习,天天向上!')

        print(mo)
    print('好好学习,天天向上!')

这里使用了@contextlib.contextmanager装饰器以及yield关键字来实现上下文管理,在yield关键字以上的部分充当__enter__方法,在yield方法以下的部分充当__exit__方法,而yield关键词产出的值会交给as子句后面指定的变量。

总结

虽然with语句在我们的代码中频繁会被用到,但是其间的实现过程可能还不是很懂,希望这一文章会在你以后使用with语句时会有所帮助!

同步更新于个人博客系统:上下文管理器和with块

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值