Python - if 语句之外得 else 块

这个语言功能不是什么秘密,只不过没有得到重视:else 子句不仅能在if 语句中使用,还可以在for、while 和 try 语句中使用。

for/else、while/else 和 try/else 的语义联系紧密,不过与if/else 差别很大。

else 子句的规则如下:

  • for : 仅当for 循环运行完毕时(即 for 循环没有被break 语句中止) 才运行else 块

  • while: 仅当while 循环没有 被 break 语句中止 才运行 else 块

  • try: 仅当try 块没有抛出异常时才运行else 块。官方文档还指出:"else 子句抛出的异常不由前面的expect 子句处理"

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

在这些语句中使用else 子句通常能让代码更易于阅读,而且能省去一些麻烦,不用设置控制标志或者添加额外的if 语句。

如下案例:

list = [1, 2, 3]

flag = False
for item in list:
    if item == 4:
        flag = True
        break

if flag:
    print('找到相关数据')
else:
    print(f'未找到相关逻辑')

完全等价于:

list = [1, 2, 3]

for item in list:
    if item == 4:
        break
else:
    print('未找到相关数据')
    # 执行未找到逻辑

一开始,你可能会觉得没必要再 try/expect 块中使用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 then permission)。这是一种常用的Python 编程风格,先假定存在有效的键或属性,如果假设不成立,那么捕获异常,这种风格简单明快,特点是 代码中有很多 try 和 except 语句。与其他很多语言一样(例如C语言),这种风格的对立面是LBYL 风格。

接下来,Python 术语表定义了LBYL。

  • LBYL
    三思而后行(Look befor you leap)。这种编程风格在调用函数或查找属性或键之前显式测试前提条件。与EAFP风格相比,这种风格的特点是代码中有很多if 语句,在多线程环境中,LBYL风格可能会在"检查" 个 "行事" 的 空隙引入条件竞争。例如,对
    if key in mapping: return mapping[key] 这段代码来说,如果在测试之后————但在查找之前————另一个线程从映射中删除了那个键,那么这段代码就会失败。这个问题可以使用锁或者EAFP 风格解决
posted @   chuangzhou  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2022-06-15 Jmeter - 使用问题记录
点击右上角即可分享
微信分享提示