在try / except块中创建一个变量被认为是一种不好的做法吗?

时间:2017-08-17 10:30:14

标签: python exception-handling try-catch

让我们考虑这个例子 - 代码返回列表None中的第一个li值的索引(如果存在)或最后一个元素的索引{{1 } {}不存在于None

我可以检查列表中的“无”,但使用ifs并不是首选方式 - Dive Into Python鼓励使用异常,因为它们被认为更快并且使代码更清晰(请参阅this问题)。所以我提出了三种方法:

1

li
在try / except块中声明了

try: my_index = li.index(None) except ValueError: my_index = len(li) - 1 print my_index 。减少行数,无冗余声明。可能的问题 - 不同的异常类型将导致无法创建my_index并导致my_index上的脚本崩溃。

2

print
在try / except之前声明了

my_index = None # or anything else try: my_index = li.index(None) except ValueError: my_index = len(li) - 1 print my_index ,并且无论发生什么异常,都会分配一个值。缺点 - 更多线条,看起来多余。

3。 编辑:无法工作 - 无论尝试/除结果

my_index

优点 - 始终有效(或至少我认为如此)。缺点 - 我从未见过有人使用try: my_index = li.index(None) except ValueError: my_index = len(li) - 1 finally: my_index = None # or anything else print my_index 来完成我的整个Python体验,这种情况必然会发生。

哪种方法被认为是首选和pythonic方式?也许有更好的解决方案?

4 个答案:

答案 0 :(得分:2)

try:
    my_index = li.index(None)
except ValueError:
    my_index = len(li) - 1

print my_index
     

可能存在的问题 - 不同的异常类型将导致my_index无法创建print并导致脚本崩溃。

呃,不。如果引发任何其他异常,则整个代码块将被中止,因为异常会冒泡到调用者。因此,如果引发除ValueError之外的任何其他异常类型,则永远不会执行print。这是一个非常理智的行为:您处理预期的错误并且可以处理,并让其他错误导致整个块中止,可能是整个脚本。这是您想要的最安全,最简洁的解决方案。

答案 1 :(得分:1)

第三种选择不起作用。查看finally上的文档  (强调我的):

  

在离开try语句之前总是执行finally子句,是否发生了异常。

所以在第三个选项中,无论发生什么,my_index总是没有。

这给我们留下了第一个和第二个选项。值得注意的是,第二个是你在大多数静态类型语言中看到的。然而,Python稍微宽松一点,允许使用任何一个选项。

我认为您关于非ValueError的异常的论点无效。另一个例外是暂停执行并返回调用者,因此永远不会达到打印。所以第一个解决方案应该可以正常工作。

答案 2 :(得分:1)

++正如@deceze注意到的那样,除了ValueError:只会捕获这个类的错误,而不会捕获其他错误。

如果您确实需要以不同方式处理不同的错误情况,可以提供更多例外条款:

try:
    ...
except (ValueError, TypeError, ...):
    ...

中除之外的序列也受支持:

{{1}}

+++如果传递空列表,您应该考虑代码需要返回什么:-1?提出异常?

答案 3 :(得分:0)

我认为这是使用例外的示例。虽然Python使用异常作为"通常"编程构造以降低复杂性,这是我认为增加复杂性的一个案例。您的代码告诉我my_index必须在这些行之后保留一个值,并且您希望li是可迭代的,即使在异常发生时也是如此。这个例外ValueErrorNone不在列表中的结果,是一个额外的复杂性,只有按惯例才能理解 - 而且,你确定它不是IndexError可能被抛出?你看,恕我​​直言的构造

if None in li: my_index = li.index(None)
else         : my_index = len(li) - 1

不会抛出半年内遇到此代码的程序员,也许是你自己,在理解你的程序逻辑的轨道上,而有例外的版本将导致额外的脑力劳动,如果你的预期提出了问题可能的例外和反应是完整和正确的。只有当这是一个真正非常重要的性能代码时,你才应该试图避开双重搜索。