Python中的with与上下文管理器

详细见:https://blog.csdn.net/weixin_35653315/article/details/78158735

with…[as…]

主要用于对象的获取和释放,以及函数默认参数的设定。类似于try…finally…

上下文管理对象(Context Manager, CM)

主要有两个协议方法为__enter__与__exit__, 前者在进入with代码块时执行, 后者在退出时执行.

原始简单cm:

# encoding=utf-8
# !/usr/local/bin/Python3
class reverse_print():
    def __enter__(self):
        # 这个方法在进入with block时执行.
        print('enter with block.')
        import sys
        self.origin_write = sys.stdout.write
        sys.stdout.write = self.new_print# Python2里这个对象不可修改, Python3可以
        return 'HELLO, I AM WITH'# 被 as 接收
    def new_print(self, s):
        self.origin_write(s[::-1])

    def __exit__(self, exception_type, exception_code, traceback):
        # 跳出with block时执行.
        # 处理异常(这儿就忽略吧), 恢复进入with时的修改
        import sys
        sys.stdout.write = self.origin_write
        print('exit with block')

print('before with:', 'hello')
with reverse_print() as cmo:
    print('hello')
    print(cmo)
print('after with:','hello')
print(cmo)

输出为:

before with: hello
enter with block.
olleh
HTIW MA I ,OLLEH
exit with block
after with: hello
HELLO, I AM WITH

这段代码展示了CMO的两个关键点:

  1. __enter__在进入with时执行. 它的返回值会被as接收.
  2. exit 在退出with时执行, 需要将在__enter__对context作出的修改恢复成原样.

使用contextlib.contextmanager 简化CM实现:

import contextlib
@contextlib.contextmanager
def reverse_print():
    # 这个方法在进入with block时执行.
    import sys
    origin_write = sys.stdout.write
    print('enter with block.')
    def new_print(s):
        origin_write(s[::-1])
    sys.stdout.write = new_print# Python2里这个对象不可修改, Python3可以
    yield 'HELLO, I AM WITH'

    # 跳出with block时执行.
    # 处理异常(这儿就忽略吧), 恢复进入with时的修改
    sys.stdout.write = origin_write
    print('exit with block')

用生成器函数重写后的CM, 调用方式与调用效果和用class实现时一模一样.
大概原理:

  1. 通过修饰器将生成器函数封装到一个CMO class里
  2. yield之前的代码在__enter__里执行, 之后的代码在__exit__里执行. yield本身的作用相当于__enter__里的return.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值