美文网首页
Fluent Python笔记--上下文管理器

Fluent Python笔记--上下文管理器

作者: MontyOak | 来源:发表于2018-04-25 20:06 被阅读12次

    所谓上下文管理器,就是Python中常见的with...as...语法。它实质上包含__enter__方法和__exit__方法(可以参考我的这篇文章)。
    其中__enter__方法的入参只有实例绑定self。而__exit__方法的入参则除了self还有exc_type(异常类),exc_value(异常实例),traceback(traceback对象)。
    下面简单实现一个上下文管理器:

    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
    
    
    >>> from mirror import LookingGlass
    >>> manager = LookingGlass() 
    >>> manager
    <mirror.LookingGlass object at 0x2a578ac>
    >>> monster = manager.__enter__() 
    >>> monster == 'JABBERWOCKY' 
    eurT
    >>> monster
    'YKCOWREBBAJ'
    >>> manager
    >ca875a2x0 ta tcejbo ssalGgnikooL.rorrim<
    >>> manager.__exit__(None, None, None) 
    >>> monster
    'JABBERWOCKY 
    

    在标准库中,可以经常看见对于上下文管理器的使用:

    • sqlite3中用于管理事务
    • threading中用于维护锁、信号和条件

    除了实现__enter____exit__之外,也可以使用contextlib提供的contextmanager装饰器来简化上下文管理器的写法。

    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 
        yield 'JABBERWOCKY' 
        sys.stdout.write = original_write 
    
    
    >>> from mirror_gen import looking_glass
    >>> with looking_glass() as what: 
    ... print('Alice, Kitty and Snowdrop')
    ... print(what)
    ...
    pordwonS dna yttiK ,ecilA
    YKCOWREBBAJ
    >>> what
    'JABBERWOCKY'
    

    contextlib.contextmanager 装饰器会把函数包装成实现__enter____exit__ 方法的类。
    其中__enter__方法有如下作用:
    (1) 调用生成器函数,保存生成器对象(这里把它称为 gen )。
    (2) 调用 next(gen) ,执行到 yield 关键字所在的位置。
    (3) 返回 next(gen) 产出的值,以便把产出的值绑定到 with/as 语句中的目标变量上。
    __exit__方法则有以下作用:
    (1) 检查有没有把异常传给 exc_type ;如果有,调用gen.throw(exception) ,在生成器函数定义体中包含 yield 关键字的那一行抛出异常。
    (2) 否则,调用 next(gen) ,继续执行生成器函数定义体中 yield 语句之后的代码。

    相关文章

      网友评论

          本文标题:Fluent Python笔记--上下文管理器

          本文链接:https://www.haomeiwen.com/subject/cygylftx.html