返回介绍

15.1 先做这个,再做那个:if 语句之外的 else 块

发布于 2024-02-05 21:59:47 字数 2393 浏览 0 评论 0 收藏 0

这个语言特性不是什么秘密,但却没有得到重视: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 块。官方文档还指出:“else 子句抛出的异常不会由前面的 except 子句处理。”

在所有情况下,如果异常或者 return、break 或 continue 语句导致控制权跳到了复合语句的主块之外,else 子句也会被跳过。

 我觉得除了 if 语句之外,其他语句选择使用 else 关键字是个错误。else 蕴含着“排他性”这层意思,例如“要么运行这个循环,要么做那件事”。可是,在循环中,else 的语义恰好相反:“运行这个循环,然后做那件事。”因此,使用 then 关键字更好。then 在 try 语句的上下文中也说得通:“尝试运行这个,然后做那件事。”可是,添加新关键字属于语言的重大变化,而 Guido 唯恐避之不及。

在这些语句中使用 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()。

在 Python 中,try/except 不仅用于处理错误,还常用于控制流程。为此,Python 官方词汇表还定义了一个缩略词(口号)。

EAFP

取得原谅比获得许可容易(easier to ask for forgiveness than permission)。这是一种常见的 Python 编程风格,先假定存在有效的键或属性,如果假定不成立,那么捕获异常。这种风格简单明快,特点是代码中有很多 try 和 except 语句。与其他很多语言一样(如 C 语言),这种风格的对立面是 LBYL 风格。

接下来,词汇表定义了 LBYL。

LBYL

三思而后行(look before you leap)。这种编程风格在调用函数或查找属性或键之前显式测试前提条件。与 EAFP 风格相反,这种风格的特点是代码中有很多 if 语句。在多线程环境中,LBYL 风格可能会在“检查”和“行事”的空当引入条件竞争。例如,对 if key in mapping: return mapping[key] 这段代码来说,如果在测试之后,但在查找之前,另一个线程从映射中删除了那个键,那么这段代码就会失败。这个问题可以使用锁或者 EAFP 风格解决。

如果选择使用 EAFP 风格,那就要更深入地了解 else 子句,并在 try/except 语句中合理使用。

下面探讨本章的主要话题:强大的 with 语句。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文