zoukankan      html  css  js  c++  java
  • Python中With的用法

    在看Dive Into Python中有关描述文件读写那章节的时候,看到了有关with的用法,查阅下相关资料,记录下来,以备后用。

    官方的reference上有关with statement是这样说的,With申明把由context manager定义的方法的执行块包装起来。这样可以把try...except...finally的使用模式封装起来已被之后方便重用。

    官方的定义如下:

    1 with_stmt ::=  "with" with_item ("," with_item)* ":" suite
    2 with_item ::=  expression ["as" target]

    只有一个"item"的with申明的执行过程如下:

    1. 计算出内容表达式(context expression)以获取内容管理(context manager),该表达式是在with_item中给出的expression。
    2. 内容管理器(context manager)加载__exit__()方法以备之后使用
    3. 内容管理器(context manager)触发__enter__()方法
    4. 假如一个目标(with_item)包含在with申明中,那么__enter__()的返回值将赋值给该目标。注意:With申明保证如果__enter__()函数的执行没有报错,那么__exit__()将总是执行。 如果在赋值给目标(with_item)的过程中出错,那么被视作该错误是在执行程序组中发生的。参考第六步
    5. 执行程序组(suite)
    6. 内容管理器(context manager)中的__exit__()方法触发。假如程序组中出现异常或错误,那对应的type,value,以及traceback全部传入__exit__()方法中去。否则,三个None值传入方法中去。

    如果程序组中由于异常退出了,并且__exit__()的返回值为假,那么该异常重新引发。假如返回值为真,那么忽略该异常,继续执行With申明之后的程序。

    如果程序组中并非由于异常退出,忽略__exit__()的返回值,该干嘛干嘛。

    多个目标(with_item)在with申明中的情况,内容管理器(context manager)将其看做多个with申明嵌套。例子如下:

    1 with A() as a, B() as b:
    2     suite

    同于:

    1 with A() as a:
    2     with B() as b:
    3         suite

    以上是With申明具体的内部执行过程,可以看出,其中最核心是内容管理器(context manager),所以我又查阅了有关with申明的内容管理器(with statment context managers)的相关内容。

    Context Manager主要是用来管理在with申明中定义的运行时内容(runtime context),也可以说是一种环境,一个状态。 该管理器实现了两个方法,一个是__enter__()方法,一个是__exit__()方法。

    __enter__()方法主要是进入运行时内容(runtime context)并返回与之相对应的对象。 该方法的返回值的会绑定到使用该context Manager的with申明AS标识符之后的内容。举个例子:

    1 with open(r'D:/test.txt', 'r', encoding='utf-8') as a_file:
    2     process(a_file)

    该内容管理器(context manager)中的__enter__()方法返回的是一个文件对象,该对象赋值给了a_file。

    在举个例子,浮点型数据运算时需要设定一个计算环境(contexts),该环境可以设定精度,进位的规则,决定哪些中情况视为异常,限制指数范围等等。可以使用getcontext()和setcontext()方法来实现,也可以用localcontext() 和with申明结合的方法来实现。

    1 from decimal import localcontext
    2 
    3 with localcontext() as ctx:
    4     ctx.prec = 42   # Perform a high precision calculation
    5     s = calculate_something()
    6 s = +s  # Round the final result back to the default precision

    __exit__(exc_type, exc_val, exc_tb)方法就是退出这个运行时内容或环境(runtime context)并返回一个布尔值的变量来确定是否忽略中途出现的异常情况。如果中途在with申明中的执行体中出现了什么问题。就会把对应的异常类型,值以及回溯信息传给该方法,没有异常就传入None。如果有异常传入并且布尔值为真就忽略该异常,如果有异常传入但布尔值为假就像正常一样抛出异常。内容管理器的好处就如之前所说一样就是把try...except...finally的使用模式封装起来已被之后方便重用。

    有关contextlib的内容将之后更新。

  • 相关阅读:
    理解Java虚拟机——Java内存模型管理
    Java 使用fastjson 将 json字符串写到文件中去
    java 如何调用 linux or mac 命令行
    MacOS 编译 openjdk8 并导入 Clion 调试
    linux ls 命令超级详解
    小 Q 与树 (点分治)
    mysql 索引策略
    java中serialVersionUID作用
    通过源码分析Spring Security用户认证流程
    使用PowerMockRunner和Mockito编写单元测试用例详解
  • 原文地址:https://www.cnblogs.com/cleverxy/p/3285436.html
Copyright © 2011-2022 走看看