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 块中做什么。

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

  1. 第15章 上下文管理器和else块

    #<流流畅的Python>第15章 上下文管理器和else块 #15.1 先做这个,再做那个:if语句之外的else块 #else子句不仅能在if语句中使用,还能在for.while和tr ...

  2. Python 上下文管理器和else块

    最终,上下文管理器可能几乎与子程序(subroutine)本身一样重要.目前,我们只了解了上下文管理器的皮毛--Basic 语言有with 语句,而且很多语言都有.但是,在各种语言中 with 语句的 ...

  3. 上下文管理器和else块

    一.if 语句之外的 else块 else 子句不仅能在 if 语句中使用,还能在for.while和try语句中使用. (1)for :仅当 for 循环运行完毕时(即 for 循环没有被break ...

  4. python中的with与上下文管理器

    #转载请留言联系 很多人平时需要打开文件进行读取写入操作时,通常这样: f = open('文件路径','w') f.write(data) f.close 这样写有一个潜在的问题,如果在调用 wri ...

  5. 浅淡python中的with,上下文管理器

    例子一 首先来看一段代码: class Foo(object): def __init__(self): print('实例化一个对象') def __enter__(self): print('进入 ...

  6. python之with语句结合上下文管理器

    所谓上下文管理器即在一个类中重写了__enter__方法和__exit__方法的类就可以成为上下文管理器类. 我们可以通过with语句结合上下文管理器简化一些操作. 使用with语句结合自定义上下文管 ...

  7. 流畅的python第十四章可迭代的对象,迭代器和生成器学习记录

    在python中,所有集合都可以迭代,在python语言内部,迭代器用于支持 for循环 构建和扩展集合类型 逐行遍历文本文件 列表推导,字典推导和集合推导 元组拆包 调用函数时,使用*拆包实参 本章 ...

  8. 流畅的python第十九章元编程学习记录

    在 Python 中,数据的属性和处理数据的方法统称属性(attribute).其实,方法只是可调用的属性.除了这二者之外,我们还可以创建特性(property),在不改变类接口的前提下,使用存取方法 ...

  9. 流畅的python第十六章协程学习记录

    从句法上看,协程与生成器类似,都是定义体中包含 yield 关键字的函数.可是,在协程中,yield 通常出现在表达式的右边(例如,datum = yield),可以产出值,也可以不产出——如果 yi ...

随机推荐

  1. JVM字节码执行引擎和动态绑定原理

    1.执行引擎 所有Java虚拟机的执行引擎都是一致的: 输入的是字节码文件,处理过程就是解析过程,最后输出执行结果. 在整个过程不同的数据在不同的结构中进行处理. 2.栈帧 jvm进行方法调用和方法执 ...

  2. [BZOJ4824][Cqoi2017]老C的键盘 树形dp+组合数

    4824: [Cqoi2017]老C的键盘 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 218  Solved: 171[Submit][Statu ...

  3. hdu5782

    官方题解不是很详细 首先有一个结论:若A=pa+sa B=pb+sb A.B串循环同构,则可以构造一个可行方案(pa,sb) (sa,pb)中有一个是最长匹配,这个不难用反证法证明. 对于s1,s2串 ...

  4. python中文ocr方案-pytesseract

    pytesseract是google维护的具有学习功能的OCR引擎,3.0以后支持中文识别. 安装: 1. 安装tesseract-ocr组件:记得同步下载简体中文与英文语言包. 2. 安装PIL,需 ...

  5. 日志rsyslog

    (1)日志基础 1)简介 rsyslog:记录大部分与系统操作有关,例如安全,认证sshd,su,计划任务at,cron rsyslog日志可以存在本地,也可以存放在远程服务器 2)常见的日志文件 / ...

  6. 在CentOS6或RHEL6恢复上ext4文件系统误删除的文件

    首先说明: [root@CentOS6 ~]# rm -rf / //这条命令不可以执行 [root@CentOS6 ~]# rm -rf /* //这条命令可以执行,别去试 ext4文件系统上误删除 ...

  7. EasyUI学习总结(六)——EasyUI布局(转载)

    本文转载自:http://www.cnblogs.com/xdp-gacl/p/4088198.html 一.EasyUI布局介绍 easyUI布局容器包括东.西.南.北.中五个区域,其中中心面板是必 ...

  8. RUP你知道多少?

    RUP 相信学UML的同学,对此都很耳熟,当然也眼熟,可是,对于RUP,你了解多少呢? 首先,什么是RUP? RUP是Rational UnifiedProcess,统一软件开发过程,是一个面向对象且 ...

  9. C++中的读入输出优化及清新脱俗的宏命令

    C和C++有了#define,从此它就变了模样 宏命令就是#define,#if,#error之类的 本文主要介绍宏命令和相关的骚操作 读入输出优化 inline int read() { int a ...

  10. bzoj 2038 小Z的袜子(hose)(莫队算法)

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 11542  Solved: 5166[Sub ...