一、 上下文管理器和 with 块
上下文管理器对象存在的目的是管理 with 语句,就像迭代器的存在是为了管理 for 语句一样。with 语句的目的是简化一些常用的 try/finally
结构。这种结构可以保证一段代码运行完毕后执行某项 操作,即便那段代码由于 return
语句、异常或 sys.exit()
调用而终止,也执行指定的操作。finally
子句中的代码通常用于释放重要的资源,或者还原临时改变的状态。
上下文管理器接口包含 __enter__
和 __exit__
两个方法。with 语句开始运行时,Python 在上下文管 理器对象上调用 __enter__
方法。with 块运行结束,或者由于什么原因终止后,Python 在上下文管理器 对象上调用 __exit__
方法。
** 把文件对象当成上下文管理器使用 **
# fp 绑定打开的文件,因为文件的 __enter__ 方法返回 self。
with open('demo10.py') as fp:
# 从 fp 中读取 60 个 Unicode 字符
src = fp.read(60)
print(fp) # <_io.TextIOWrapper name='demo10.py' mode='r' encoding='cp936'>
# ❺ 但是不能使用 fp 继续读取文本,因为在 with 块的末尾,Python 调用 TextIOWrapper.__exit__ 方
# 法把文件关闭了。
print(fp.read(60)) # 这个会报错
碰巧,open()
函数返回一个 TextIOWrapper
实例,而该实例的 __enter__
方法返回 self。不过,其 他类的 __enter__
方法可能会返回其他对象,而不返回上下文管理器实例。不管控制流以哪种方式退出 with 块,都在上下文管理器对象上调用 __exit__
方法,而不是在 __enter_
方法返回的对象上调用。with
语句的 as
子句是可选的。对 open
函数来说,必须加上 as
子句,以便获取文件的引用,在引用上 调用方法。不过,有些上下文管理器返回 None
,因为没什么有用的对象能提供给用户。
二、 if 语句之外的 else 块
else 子句不仅能在 if 语句中使用,还能在 for、while 和 try 语句中使用。
else 子句的规则如下。
-
for 仅当 for 循环运行完毕时(即 for 循环没有被 break 语句中止)才运行 else 块。
-
while 仅当 while 循环因条件为假值而退出时(即 while 循环没有被 break 语句中止)才运行 else 块。
-
try 仅当 try 块没有抛出异常时才运行 else 块。官方文档还指出:“else 子句抛出的异常不由前面的 except 子句处理。”
在所有情况下,如果异常或者 return、break 或 continue 语句导致控制权跳到了复合语句的主块之 外,则 else 子句也被跳过。
for item in my_list:
if item.flavor == 'banana':
break
else:
raise ValueError('No banana flavor found!')
try:
dangerous_call()
after_call()
except OSError:
log('OSError...')
原文始发于微信公众号(Python之家):Python深入-14-with上下文
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/198365.html