zoukankan      html  css  js  c++  java
  • Python 的with关键字

    Python 的with关键字

    看别人的代码时,with关键字经常会出现,博主决定梳理一下with以及python中上下文(context)的概念

    1. 上下文管理器概念

    Context Manager指的是python在执行一段代码前后,做的一些预处理和后处理,使得代码块运行处于一个小的环境(surrounding),出了这个小环境之后,资源释放,环境中的各种配置也失效。

    例如在打开文件需要关闭,连接数据库后需要关闭连接。很多优雅第三方库也会利用上下文使得对象进入特定的某种状态。

    2. with关键字

    with的基本用法如下:

    with EXPR as VAR:
      BLOCK
    

    其中发生了一系列过程:

    1. EXPR语句被执行,得到ContextManager
    2. 调用ContextManager.__enter__方法
    3. 如果有as VAR,则ContextManager.__enter__的返回值赋给VAR,否则就不管返回值
    4. 执行BLOCK,如果有VAR被用到,就和普通变量一样
    5. 调用ContextManager.__exit__方法
      • __exit__有三个参数:type, value, traceback,BLOCK出异常时会得到对应值,正常情况就都为None
      • __exit__返回值为True表示BLOCK中出现的异常可以忽略,False表示需要raise

    3. 例子

    3.1 资源操作:

    class CustomOpen:
        def __init__(self, filename: str):
            self.__filename = filename
            self.__handler = None
        
        def __enter__(self):
            print("enter......")
            self.__handler = open(self.__filename)
            return self.__handler
        
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("exit...", exc_type, exc_val, exc_tb)
            if self.__handler is not None:
                self.__handler.close()
            return True
    
    
    with CustomOpen("hello.txt") as f:
        print(f.read())
    

    运行结果:

    enter......
    hello world
    exit... None None None
    

    3.2 状态维护

    class CustomBrain:
        def __init__(self):
            self.__status = "normal"
        
        def say(self):
            if self.__status == "normal":
                print("You're a great man")
            elif self.__status == "special":
                print("You are a very outstanding person ")
    
        def __enter__(self):
            self.__status = "special"
    
        
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.__status = "normal"
    
    
    brain = CustomBrain()
    brain.say() # 普通状态
    
    # 可以通过上下文维护一些状态
    with brain:
        brain.say() # 特殊状态
    
    brain.say() # 普通状态
    

    运行结果:

    You're a great man
    You are a very outstanding person
    You're a great man
    

    4. 使用contextlib简化编写

    python内置的标准库contextlib可以是的代码书写更加简洁,本质是一样的。比较有用的是contextlib.contextmanager这个装饰器,被装饰的函数在yield的前面相当于__enter__,yield的后面相当于__exit__,yield本身的返回值赋给as后的变量

    所以第一个示例可以这么写:

    from contextlib import contextmanager
    
    @contextmanager
    def custom_open(filename: str):
        print("enter......")
        handler = open(filename)
    
        yield handler
    
        print("exit...")
        handler.close()
    
    
    with custom_open("hello.txt") as f:
        print(f.read())
    

    还是优雅了许多~

  • 相关阅读:
    BZOJ.3884.上帝与集合的正确用法(扩展欧拉定理)
    HDU.5608.function(杜教筛)
    HDU.5628.Clarke and math(狄利克雷卷积 快速幂)
    51Nod.1244.莫比乌斯函数之和(杜教筛)
    SPOJ.Visible Lattice Points(莫比乌斯反演)
    BZOJ.2301.[HAOI2011]Problem B(莫比乌斯反演 容斥)
    BZOJ.2242.[SDOI2011]计算器(扩展欧几里得 BSGS)
    Codeforces757E.Bash Plays With Functions(积性函数 DP)
    插值法
    2、Windows下安装配置Redis
  • 原文地址:https://www.cnblogs.com/fanghao/p/11722361.html
Copyright © 2011-2022 走看看