文章目录

  • 1. else
  • 2. with上下文管理器
  • 3. contextlib模块实用工具
  • 4. @contextmanager 装饰器

learn from 《流畅的python》

1. else

  • for/else、while/else 和 try/else
    前两者 只有在 没有被break 时,才会运行 else
    try 块中没有异常抛出时 才运行 else
for i in range(3):print(i)
else:print("finish, no break")# finish, no breakfor i in range(3):if i == 2:breakprint(i)
else:print("break")# 无输出i = 0
while i < 3:print(i)i += 1
else:print("no break") # no breaki = 0
while i < 3:if i==2:breakprint(i)i += 1
else:print("break") # 无输出arr = [0]
try:arr[0] = 1
except:print("error") # 无输出
else:print("no error, run else")# no error, run elsearr = []
try:arr[0] = 0
except:print("error") # error
else:print("error, will not run else") # 无输出
finally:print("finish") # finish
# finally 子句中的代 码通常用于释放重要的资源,或者还原临时变更的状态

else 这么用的比较少

2. with上下文管理器

上下文管理器协议包含 __enter____exit__ 两个方法

  • with 语句 运行时,会在上下文管理器对象上调用 __enter__ 方法
  • with 语句 结束后,会在上下文管理器对象上调用 __exit__ 方法,以此扮 演 finally 子句的角色(释放重要的资源,或者 还原临时变更的状态),如 关闭文件等
class LookingGlass:def __enter__(self): # 没有其它的参数了import sysself.original_write = sys.stdout.writesys.stdout.write = self.reverse_writereturn 'ABCD'def reverse_write(self, text): # 反转字符串,实现输出self.original_write(text[::-1])def __exit__(self, exc_type, exc_value, traceback):# exc_type 异常类# exc_value 异常实例# traceback 对象# 在 try/finally 语句的 finally 块中调用 sys.exc_info()# 得到的就是 __exit__ 接收的这三个参数import syssys.stdout.write = self.original_writeif exc_type is ZeroDivisionError:print('Please DO NOT divide by zero!')return Truewith LookingGlass() as what:# 进入 __enter__ 函数时返回的 ABCD 字符串存入 whatprint("Michael learning python")# nohtyp gninrael leahciMprint(what)# DCBA
print("Michael learning python")
# Michael learning python
print(what)
# ABCD
manager = LookingGlass()
print(manager)
# <__main__.LookingGlass object at 0x00000231226F2190>
string = manager.__enter__()
print(string)  # DCBA
print(string == "ABCD")  # eurT, 所有的输出经过管理器的 反向输出处理了
print(string == "DCBA")  # eslaF, 所有的输出经过管理器的 反向输出处理了
print(manager)
# >0912F62213200000x0 ta tcejbo ssalGgnikooL.__niam__<
manager.__exit__(None, None, None) # 还原了正常的输出
print(string)  # ABCD

3. contextlib模块实用工具

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

使用最广泛的是 @contextmanager 装饰 器,因此要格外留心
这个装饰器也有迷惑人的一面,因为它与迭代 无关,却要 使用 yield 语句

4. @contextmanager 装饰器

  • @contextmanager 装饰器能减少代码量,因为 不用编写一个完整的类,定义 __enter__ 和 __exit__ 方法,而 只需实现 有一个 yield 语句的生成器,生成想让 __enter__ 方法返回的值
  • 在使用 @contextmanager 装饰的生成器中,yield 语句的作用是 把函数的定义体分成两部分:
    yield 语句前面的所有代码在 with 块开始时 (即解释器调用 __enter__ 方法时)执行
    yield 语句后面的代码在 with 块结束时(即调用 __exit__ 方法时)执行
import contextlib@contextlib.contextmanager
def looking_glass1():import sysoriginal_write = sys.stdout.writedef reverse_write(text):original_write(text[::-1])sys.stdout.write = reverse_writeyield 'ABCD'  # 产出的值绑定到 as 目标上# 执行 with 块代码时,函数会在这里暂停sys.stdout.write = original_write#  控制权一旦跳出 with 块,继续执行 yield 语句之后的代码with looking_glass1() as what:print("Michael learning python")print(what)
# nohtyp gninrael leahciM
# DCBA
print("Michael learning python")
print(what)
# Michael learning python
# ABCD

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

用于原地重写文件的上下文管理器

import csv
with inplace(csvfilename, 'r', newline='') as (infh, outfh): reader = csv.reader(infh) writer = csv.writer(outfh) for row in reader: row += ['new', 'columns'] writer.writerow(row)

inplace 函数是个上下文管理器,为同一个文件提供了两个句柄(例中的 infh 和 outfh),以便同时读写同一个文件。比标准库中的 fileinput.input 函数 易用

python 上下文管理器、 else 块、@contextmanager相关推荐

  1. Python 上下文管理器和with块 二

    标准库中还有个contextlib 模块,提供一些实用工具, closing 如果对象提供了 close() 方法,但没有实现 __enter__/__exit__ 协议,那么可以使用这个函数构建上下 ...

  2. Python 上下文管理器和with块 一

    上下文管理器对象存在的目的是管理 with 语句,就像迭代器的存在是为了管理 for 语句一样 上下文管理器协议包含 __enter__ 和 __exit__ 两个方法 把值绑定到目标变量上(as 子 ...

  3. Python上下文管理器的魔力

    点击关注我哦 一篇文章带你了解Python上下文管理器的魔力 小编将为您准备一份很棒的Python上下文管理器使用指南,这将使您的代码更具可读性和可靠性,降低您的错误发生率. 资源管理器是我们在任何编 ...

  4. 此上下文中不支持函数定义。请在代码文件中创建函数。_深入解析Python上下文管理器,让你不再迷茫!...

    1. 上下文管理器 一个类只要实现了 __enter__() 和 __exit__() 这个两个方法,通过该类创建的对象我们就称之为上下文管理器. 上下文管理器可以使用 with 语句,with语句之 ...

  5. 爱上python系列------python上下文管理器(二):对suppress进行装饰器重新实现

    python上下文管理器可以做的事情简直不能太多 这不,官方的文档实现了一个方法suppress,用于处理异常 from contextlib import suppresswith suppress ...

  6. Python 上下文管理器和 with 语句

    1. 上下文管理器概念 什么是 Python 的上下文管理器(Context Managers)呢? ​ 含有 __enter__ 和 __exit__ 方法的对象就是.上下文管理器存在的目的是管理 ...

  7. Python 上下文管理器与with语句

    Python中把进入代码块前调用__enter__ 方法并在离开代码块后调用__exit__方法的对象作为上下文管理器,本文中我们就来深入解析Python中的上下文管理器,来看看上下文管理器的作用及用 ...

  8. python意外退出_有趣的Python上下文管理器

    阅读耗时:9分钟 目录 编写自定义上下文管理器 从生成器到上下文管理器 将上下文管理器编写为装饰器 嵌套式上下文管理器 组合式上下文管理器 利用用上下文管理器创建SQLAlchemy session ...

  9. python上下文管理器

    什么是上下文管理器? 基本语法 with open('test.txt') as f:print f.readlines() 1. 上下文表达式:with open('test.txt') as f: ...

最新文章

  1. 【Python】Python中*args 和**kwargs的用法
  2. 使mysql查询条件区分大小写 数据库搜索中大小写敏感性
  3. 小米故事:凭什么把MIUI用户做到1亿 | PMcaff-干货
  4. 2020-10-03
  5. java焦点事件如何使用_Java中如何释放鼠标事件的焦?
  6. 《嵌入式系统项目分析入门与实践》 读后感(1)
  7. Python 3.9 正式版要来了,会有哪些新特性?
  8. 实现平衡二叉排序树的各种算法(包括二叉树的递归遍历、非递归遍历)
  9. 学习笔记: Django之初见
  10. php中的get_called_class()方法
  11. 使用idea把Svn分支合并到主干上
  12. js获取某年某月某天是第几周
  13. 不懂面试官想要哪种数据分析师,简历写的再好也没用!文末有福利
  14. Windows 10 21H2正式版镜像
  15. 移动互联网草根狂欢:三四线城镇用户价值凸显
  16. HazelEngine 学习记录 - 2D Renderer Transforms and 2D Renderer Textures
  17. selenium登录QQ邮箱(附带滑动解锁)
  18. 以IM为例看58同城典型技术架构演变
  19. 都说C++难,那么它到底难在了哪里?
  20. 【Github】使用github

热门文章

  1. mysql5.7.11解压版安装_Mysql5.7.11在windows10上的安装与配置(解压版)
  2. 清华大学《操作系统》(八):置换算法
  3. 面向对象:实例化的对象调用类方法 db.Column()
  4. 制作根文件系统时的错误解决
  5. cmdline常用参数
  6. CodeForces - 627A
  7. ios 后台下载,断点续传总结
  8. webpack-安装
  9. vue 组件之间数据传递(七)
  10. linux tar order