• with上下文管理


    介绍

    with上下文管理在python中实现了__enter__和__exit__方法,即支持上下文管理器协议。上下文管理器就是支持上下文管理器协议的对象,它是为了with而生。当with语句在开始运行时,会在上下文管理器对象上调用 enter 方法。with语句运行结束后,会在上下文管理器对象上调用 exit 方法

    with的语法:

    with EXPR as VAR:    BLOCK
    

    这是上面语法的伪代码:

    mgr = (EXPR)   
    exit = type(mgr).__exit__  # Not calling it yet
    value = type(mgr).__enter__(mgr)    
    exc = True     
    try:
        try:
            VAR = value  # Only if "as VAR" is present
            BLOCK
        except:
            # The exceptional case is handled here
            exc = False
            if not exit(mgr, *sys.exc_info()):
                raise
            # The exception is swallowed if exit() returns true
    finally:
        # The normal and non-local-goto cases are handled here
        if exc:
            exit(mgr, None, None, None)
    

    1、生成上下文管理器mgr
    2、如果没有发现__exit__, __enter__两个方法,解释器会抛出AttributeError异常
    3、调用上下文管理器的 enter() 方法
    4、如果语法里的as VAR没有写,那么 伪代码里的 VAR= 这部分也会同样被忽略
    5、如果BLOCK中的代码正常结束,或者是通过break, continue ,return 来结束,exit()会使用三个None的参数来返回
    6、如果执行过程中出现异常,则使用 sys.exc_info的异常信息为参数调用 exit(exc_type, exc_value, exc_traceback)

    之前我们对文件的操作是这样的:

    try:
        f = open('filename')
    except:
        print("Unexpected error:", sys.exc_info()[0])
    else:
        print(f.readlines())
        f.close()
    

    现在有了with语句可以使代码更加简洁,减少编码量,下面的语句会在执行完后自动关闭文件(即使出现异常也会)。:

    with open('example.info', 'r') as f:
        print(f.readlines())
    

    一个例子:

    class TmpTest:
        def __init__(self,filename):
            self.filename=filename
        def __enter__(self):
            self.f = open(self.filename, 'r')
           # return self.f
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.f.close()
    
    test=TmpTest('file')
    
    with test as t:
        print ('test result: {}'.format(t))
    

    返回:

    test result: None
    

    这个例子里面__enter__没有返回,所以with语句里的"as t"到的是None,修改一下上面的例子:

    class TmpTest:
        def __init__(self,filename):
            self.filename=filename
        def __enter__(self):
            self.f = open(self.filename, 'r')
            return self.f
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.f.close()
    
    test=TmpTest('file')
    
    with test as t:
        print ('test result: {}'.format(t))
    

    返回:

    test result: <_io.TextIOWrapper name='file' mode='r' encoding='cp936'>
    

    如果在__init__或者__enter__中抛出异常,则不会进入到__exit__中:

    class TmpTest:
        def __init__(self,filename):
            self.filename=filename
            print("__init__")
            raise ImportError
        def __enter__(self):
            self.f = open(self.filename, 'r')
            print("__enter__")
            return self.f
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("__exit__")
            self.f.close()
    
    test=TmpTest('file')
    with test as t:
        print ('test result: {}'.format(t))
    

    返回:

    __init__
    Traceback (most recent call last):
      File "D:/pythonScript/leetcode/leetcode.py", line 14, in <module>
        test=TmpTest('file')
      File "D:/pythonScript/leetcode/leetcode.py", line 5, in __init__
        raise ImportError
    ImportError
    

    如果在__exit__中返回True,则不会产生异常:

    class TmpTest:
        def __init__(self,filename):
            self.filename=filename
            print("__init__")
    
        def __enter__(self):
            self.f = open(self.filename, 'r')
            print("__enter__")
            return self.f
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("__exit__ {} ".format(exc_type))
            self.f.close()
            return True
    
    test=TmpTest('file')
    with test as t:
        print ('test result: {}'.format(t))
        raise ImportError
    print("no error")
    

    返回:

    __init__
    __enter__
    test result: <_io.TextIOWrapper name='file' mode='r' encoding='cp936'>
    __exit__ <class 'ImportError'>
    no error
    

    笔试题举例

    
    """
    面试题
    请在Context类中添加代码完成该类的实现
    class Context:
        pass
    
    with Context() as ctx:
        ctx.do_something()
    """
    class Context:
        def __enter__(self):
            return self
        
        def __exit__(self, exc_type, exc_val, exc_tb):
            pass
        
        def do_something(self):
            pass
    
    with Context() as ctx:
        ctx.do_something()
    
    
  • 相关阅读:
    android 8 wifi wifi 扫描过程
    Android WiFi 日志记录(四次握手)
    Android 8 Wifi 初始化过程
    wifi 通过omnipeek 查看 pmf是否生效
    qualcomm 查看 wifi 配置生效
    Android 8 AudioPolicy 分析
    2. 观点提取和聚类代码详解
    1. pyhanlp介绍和简单应用
    6. EM算法-高斯混合模型GMM+Lasso详细代码实现
    5. EM算法-高斯混合模型GMM+Lasso
  • 原文地址:https://www.cnblogs.com/ghylpb/p/12514277.html
Copyright © 2020-2023  润新知