前言
本文主要个大家介绍了关于Pythonpython/84646.html">python/205749.html">上下文管理器与else块的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。
在开始之前,我们先来看看下面这段话:
最终,上下文管理器可能几乎与子程序(subroutine)本身一样重要。目前,我们只了解了上下文管理器的皮毛……Basic 语言有with 语句,而且很多语言都有。但是,在各种语言中 with 语句的作用不同,而且做的都是简单的事,虽然可以避免不断使用点号查找属性,但是不会做事前准备和事后清理。不要觉得名字一样,就意味着作用也一样。with 语句是非常了不起的特性。
——Raymond Hettinger
雄辩的 Python 布道者
先做这个,再做那个:if语句之外的else块
这个语言特性不是什么秘密,但却没有得到重视:else 子句不仅能在if 语句中使用,还能在 for、while 和 try 语句中使用。for/else、while/else 和 try/else 的语义关系紧密,不过与if/else 差别很大。起初,else 这个单词的意思阻碍了我对这些特性的理解,但是最终我习惯了。
else 子句的行为如下:
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 子句也会被跳过。
在这些语句中使用 else 子句通常能让代码更易于阅读,而且能省去一些麻烦,不用设置控制标志或者添加额外的 if 语句。
在循环中使用 else 子句的方式如下述代码片段所示:
for item in my_list: if item.flavor == 'banana': break else: raise ValueError('No banana flavor found!')
一开始,你可能觉得没必要在 try/except 块中使用 else 子句。毕竟,在下述代码片段中,只有 dangerous_call()
不抛出异常,after_call()
才会执行,对吧?
try: dangerous_call() after_call() except OSError: log('OSError...')
然而,after_call()
不应该放在 try 块中。为了清晰和准确,try 块中应该只抛出预期异常的语句。因此,像下面这样写更好:
try: dangerous_call() except OSError: log('OSError...') else: after_call()
现在很明确,try 块防守的是 dangerous_call()
可能出现的错误,而不是 after_call()
。而且很明显,只有 try 块不抛出异常,才会执行after_call()
。
上下文管理器和with块
上下文管理器对象存在的目的是管理 with 语句,就像迭代器的存在是为了管理 for 语句一样。
with 语句的目的是简化 try/finally 模式。这种模式用于保证一段代码运行完毕后执行某项操作,即便那段代码由于异常、return 语句或sys.exit()
调用而中止,也会执行指定的操作。finally 子句中的代码通常用于释放重要的资源,或者还原临时变更的状态。
上下文管理器协议包含 __enter__ 和 __exit__ 两个方法。with 语句开始运行时,会在上下文管理器对象上调用 __enter__ 方法。with 语句运行结束后,会在上下文管理器对象上调用 __exit__ 方法,以此扮演 finally 子句的角色。
新闻热点
疑难解答