• 流畅的python第十五章上下文管理器和else块学习记录


    with 语句和上下文管理器
    for、while 和 try 语句的 else 子句

    with 语句会设置一个临时的上下文,交给上下文管理器对象控制,并且负责清理上下
    文。这么做能避免错误并减少样板代码,因此 API 更安全,而且更易于使用。除了自动
    关闭文件之外,with 块还有很多用途

    else 子句不仅能在 if 语句中使用,
    还能在 for、while 和 try 语句中使用

    for
      仅当 for 循环运行完毕时(即 for 循环没有被 break 语句中止)才运行 else 块。
    while
      仅当 while 循环因为条件为假值而退出时(即 while 循环没有被 break 语句中止)
    才运行 else 块。
    try
      仅当 try 块中没有异常抛出时才运行 else 块。官方文档
    (https://docs.python.org/3/reference/compound_stmts.html)还指出:“else 子句抛出的异常
    不会由前面的 except 子句处理。”
    在所有情况下,如果异常或者 return、break 或 continue 语句导致控制权跳到了复合
    语句的主块之外,else 子句也会被跳过

    上下文管理器和with块
    上下文管理器对象存在的目的是管理 with 语句,就像迭代器的存在是为了管理 for 语句
    一样。
    with 语句的目的是简化 try/finally 模式。这种模式用于保证一段代码运行完毕后执行
    某项操作,即便那段代码由于异常、return 语句或 sys.exit() 调用而中止,也会执行
    指定的操作。finally 子句中的代码通常用于释放重要的资源,或者还原临时变更的状
    态。
    上下文管理器协议包含 __enter__ 和 __exit__ 两个方法。with 语句开始运行时,会在
    上下文管理器对象上调用 __enter__ 方法。with 语句运行结束后,会在上下文管理器对
    象上调用 __exit__ 方法,以此扮演 finally 子句的角色。

    解释器调用 __enter__ 方法时,除了隐式的 self 之外,不会传入任何参数。传给
    __exit__ 方法的三个参数列举如下。
    exc_type

           异常类(例如 ZeroDivisionError)。
    exc_value
      异常实例。有时会有参数传给异常构造方法,例如错误消息,这些参数可以使用
    exc_value.args 获取。
    traceback
      traceback 对象

    。除了
    前面提到的 redirect_stdout 函数,contextlib 模块中还有一些类和其他函数,使用
    范围更广。
    closing
      如果对象提供了 close() 方法,但没有实现 __enter__/__exit__ 协议,那么可以
    使用这个函数构建上下文管理器。
    suppress
      构建临时忽略指定异常的上下文管理器。
    @contextmanager
      这个装饰器把简单的生成器函数变成上下文管理器,这样就不用创建类去实现管理器
    协议了。
    ContextDecorator
      这是个基类,用于定义基于类的上下文管理器。这种上下文管理器也能用于装饰函
    数,在受管理的上下文中运行整个函数。
    ExitStack
      这个上下文管理器能进入多个上下文管理器。with 块结束时,ExitStack 按照后进
    先出的顺序调用栈中各个上下文管理器的 __exit__ 方法。如果事先不知道 with 块要进
    入多少个上下文管理器,可以使用这个类。例如,同时打开任意一个文件列表中的所有文
    件。

    @contextmanager 装饰器能减少创建上下文管理器的样板代码量,因为不用编写一个完
    整的类,定义 __enter__ 和 __exit__ 方法,而只需实现有一个 yield 语句的生成器,
    生成想让 __enter__ 方法返回的值。
    在使用 @contextmanager 装饰的生成器中,yield 语句的作用是把函数的定义体分成两
    部分:yield 语句前面的所有代码在 with 块开始时(即解释器调用 __enter__ 方法
    时)执行, yield 语句后面的代码在 with 块结束时(即调用 __exit__ 方法时)执行

    其实,contextlib.contextmanager 装饰器会把函数包装成实现 __enter__ 和
    __exit__ 方法的

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

    使用 @contextmanager 装饰器时,要把 yield 语句放在 try/finally 语句
    中(或者放在 with 语句中),这是无法避免的,因为我们永远不知道上下文管理器
    的用户会在 with 块中做什么。

  • 相关阅读:
    关于Vuex的actions传入多个参数的方法:
    2019最新create-react-app创建的react中使用sass/scss,以及在react中使用sass/scss公共变量的方法
    vue中怎么使用vuex
    分享一个知乎答案 最详细易懂的 js闭包
    web前端 在react中使用移动端事件,学习笔记
    闭包
    原生ajax练习-post&xml
    Ajax中Get请求与Post请求的区别
    css文件编码
    template.js模板工具案例
  • 原文地址:https://www.cnblogs.com/lgh344902118/p/8391449.html
Copyright © 2020-2023  润新知