在Python中,try-else语句有什么作用?

9

我正在努力学习Python的细节,然后遇到了try-else语句

try1_stmt ::=  "try" ":" suite
               ("except" [expression [("as" | ",") target]] ":" suite)+
               ["else" ":" suite]
               ["finally" ":" suite]

可选的else子句在try子句结束时控制流程离开时执行。 else子句中的异常不由前面的except子句处理。
我想不出这种情况何时有用。通常,在try块的末尾或else块中放置代码之间没有实际区别。
else子句有什么好处?它在一些实际代码中使用吗?

我认为else是一个通用的“如果没有except子句捕获异常,则在此处运行代码”的语句。 - slugonamission
1
@slugonamission,确实如此,但这有什么实际应用呢? - StackExchange saddens dancek
3
实际上,我很蠢(应该先阅读手册)。正如另一个链接所说(来自Emir),这是为了只在成功时执行没有错误处理的代码,然后才运行finally块。 - slugonamission
有人知道 C 的变体吗?我喜欢这种语法的样子。 - John Riselvato
1
首先,你需要在C中进行异常处理。 - wim
显示剩余2条评论
3个回答

9
通常情况下,在try块的末尾或else块中放置代码没有实际区别。那么else子句有什么用途呢?它有一个特殊用例,即在没有异常但在finally子句之前运行。这是它唯一的用例,并且没有合理的替代方案。如果没有else子句,要在最终化之前运行其他代码的唯一选择是将代码添加到try子句中。这种方式很笨拙,因为它会在原本不应该受到try块保护的代码中引发异常。很少会出现在已发布代码中运行非保护代码之前的额外用例。因此,不要指望看到许多示例。else子句的另一个用例是执行必须在未发生异常时发生且在处理异常时不会发生的操作。例如:
   recip = float('Inf')
   try:
       recip = 1 / f(x)
   except ZeroDivisionError:
       logging.info('Infinite result')
   else:
       logging.info('Finite result')

最后,try块中else子句最常见的用法是为了美化代码(将异常结果和正常结果对齐在同一缩进级别)。这种用法总是可选的,不是严格必要的。
“它在实际代码中使用吗?”
是的,在标准库中有很多例子。

1
你的示例非常易读,展示了一个实际的使用案例。非常棒的答案! - StackExchange saddens dancek
你说:“那是它的一个用例,没有合理的替代方案。” 但你没有给出任何用例(“那”指的是什么)。 - Alexey
2
当介绍你唯一的例子时,你只是重复了else:的作用(如果在try中没有异常,则在finally之前运行其代码,正如你之前已经说过,并且如文档所述),但是如果将else:部分放在try:内部,示例将仍然起同样的作用,因此它也没有提供任何(有趣的)用例。 - Alexey

4

在我看来,try块末尾多余的内容有点像代码异味。try块应该只包含你认为有可能抛出异常的行(最好只有一行)。这样可以避免无意中捕获不应该抛出异常的行所引发的异常(并且可能会处理不当)。使用else块可以更加清晰地编写代码。


我明白了。我不太习惯这样的写法,所以看起来有点难读。但是同意,tryfinally块都应该尽可能保持简短。所以如果你需要在它们之间添加一些内容,使用else就可以了。 - StackExchange saddens dancek

0
如果未来的读者偶然看到这篇文章并需要另一个例子,我可以提供一个。在我的论文中,我最终构建了以下的try-except-else-finally语句。
我正在进行大量的数值模拟。每次模拟我都使用pickle保存。这些模拟我在高性能集群(HPC)上进行。由于某种原因,自几周以来,一些pickle文件已经损坏了。我不想保存这些文件,而是宁愿删除它们。
for i range(n_simulations):
   data = simulate()

   # Save simulation data using my custom method
   filepath = save_to_pickle(data)
 
   # Custom class to reload my pickles during data processing later
   data_loader = DataLoad()
   
   # Checking if file is corrupted using the same data loader class
   try:
        data_loader.load_file(filepath)

   except Badzipfile:
       print('File is corrupted, deleting')
       delete_saved_file(filepath)

   else:
       print('Simulation success') 

   finally:
       del data_loader

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接