zoukankan      html  css  js  c++  java
  • python基础之上下文管理器

    前言

    关于计算器运行的上下文的概念,我的理解也不是很深;按我的理解就是程序在运行之前,其所需要的资源,运行环境等都会被序列化,然后加入到CPU的任务队列中,等待调度系统分配时间片执行。下面谈谈python上下文管理器的使用。

    系列文章

    上下文管理器

    • python中最常用的上下文管理器就是文件的打开和关闭了。
    with open(filename,'r') as file:
        file.read()
    
    

    原理

    • python上下文使用with触发,内部实现了__enter__和__exit__两个魔法方法。
    class context(object):
        def __init__(self):
            print('aaaa')
    
        def __enter__(self):
            print('bbbb')
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('cccc')
    
    # exc_type:异常的类型;
    # exc_val:异常的详细信息;
    # exc_tb:异常发生的位置;
    # 如果没有发生异常,以上三个值都是None
    
    with context() as f:
        '''主体逻辑'''
        print('xxxx')
    
    # 输出
    aaaa
    bbbb
    xxxx
    cccc
    
    • 当使用with触发管理器的时候,先初始化执行__init__得到一个对象,然后执行__enter__方法,再执行主体程序的逻辑,最后执行__exit__方法。

    注意

    • 当程序主体逻辑执行完毕退出with语句块或者主体逻辑代码块出现异常,则会自动执行__exit__方法,并且会把对于的异常参数传递进来;如果没有异常,传递的是None。

    • 如果主体逻辑代码发生了错误,但是__exit__函数返回True,则with语句主体逻辑代码块异常不会被抛出,终止程序;如果返回None或者False,异常会被主动raise,并终止程序。

    总结上下文管理器的完整的原理

    1. 初始化获取一个上下文管理器对象;

    2. 加载上下文管理器的 exit() 方法备用;

    3. 调用上下文管理器的 enter() 方法;如果有 as f从句,则将 enter() 方法的返回值赋给f;

    4. 执行主体逻辑代码块;

    5. 调用上下文管理器的 exit() 方法;

    python的上下文管理工具contextlib

    python内置了对于上下文管理器更优雅的管理方法

    import contextlib
    
    @contextlib.contextmanager
    def test():
        print('aaaaaa')
        try:
            yield 1
        finally:
            print('bbbbb')
    
    with test() as f:
        print('ccccc')
    
    # 输出
    aaaaaa
    ccccc
    bbbbb
    

    底层简化版的原理

    class ContextTest(object):
        def __init__(self):
            self.f = self.test()
    
        def __enter__(self):
            return next(self.f)
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            try:
                next(self.f)
            except StopIteration:
                return False
    
        def test(self):
            print('aaaaaa')
            try:
                yield 1
            finally:
                print('bbbbb')
    
    with ContextTest() as f:
        print(f)
        print('kkkkkk')
    
    
    • 说明:
    1. 先初始化一个ContextTest上下文管理器对象,得到一个对象的生成器test()

    2. 加载上下文管理器的 exit() 方法备用;

    3. 调用上下文管理器的 enter() 方法;执行next()方法唤醒test()生成器,执行yield关键字前面的代码;

    4. 执行主体逻辑代码;

    5. 调用上下文管理器的 exit() 方法;该方法调用next()方法再次唤醒生成器,执行yield关键字后面的代码;

    参考

  • 相关阅读:
    Tempter of the Bone 搜索---奇偶性剪枝
    uestc 1709 Binary Operations 位运算的灵活运用
    uestc 1072 a ^ b
    uestc Another LCIS
    武汉邀请赛 Key Logger 双向链表
    bnu 29378 Adidas vs Adivon 基础题
    中南月赛F ZZY and his little friends
    日期问题
    开灯问题
    开灯问题
  • 原文地址:https://www.cnblogs.com/cwp-bg/p/8601087.html
Copyright © 2011-2022 走看看