更好地“尝试”一些东西,并捕捉exception或testing是否可能首先避免exception?

我应该testing一下是否有效,或只是try去做,并捕获exception?

  • 有没有可靠的文件说有一种方法是优先的?
  • 是一种更pythonic

例如,我应该:

 if len(my_list) >= 4: x = my_list[3] else: x = 'NO_ABC' 

要么:

 try: x = my_list[3] except IndexError: x = 'NO_ABC' 

有些想法…
PEP 20说:

错误不应该默默通过。
除非明确沉默。

应该使用一个try而不是一个if被解释为一个错误地传递的错误? 如果是这样,你是否明确地使用这种方式来消除它,因此,它可以吗?


不是指只能做1件事情的情况; 例如:

 try: import foo except ImportError: import baz 

你应该更喜欢try/except结果是if/else

  • 加速(例如通过防止额外的查找)
  • 更干净的代码(less线/更易于阅读)

这些经常是相辅相成的。


速度起坐

在通过以下方式尝试在长列表中查找元素的情况下:

 try: x = my_list[index] except IndexError: x = 'NO_ABC' 

尝试,除了是index可能在列表中的最佳选项,通常不会引发IndexError。 这样,您可以避免通过if index < len(mylist)进行额外的查找。

Python鼓励使用exception, 您处理的是从Dive Into Python开始的一个短语。 你的例子不仅处理exception(优雅),而不是让它静静地通过 ,也只有在例外的情况下才会发现exception (因此这个词是exception !)。


更干净的代码

官方的Python文档提到了EAFP : 比权限更容易要求原谅 , Rob Knight指出, 捕获错误而不是避免错误会导致更清晰,更易读的代码。 他的例子是这样说的:

更糟糕的是(LBYL'看你跳跃')

 #check whether int conversion will raise an error if not isinstance(s, str) or not s.isdigit: return None elif len(s) > 10: #too many digits for int conversion return None else: return int(str) 

更好(EAFP:容易要求宽恕比权限)

 try: return int(str) except (TypeError, ValueError, OverflowError): #int conversion failed return None 

在这种情况下,你应该完全使用其他的东西:

 x = myDict.get("ABC", "NO_ABC") 

但是,一般来说,如果您希望testing经常失败,请使用if 。 如果testing相对于仅仅尝试操作而言是昂贵的并且如果失败则捕获exception,则使用try 。 如果这些条件中没有一个适用,那么更简单地去阅读。

如果在你做这件事之前检查是否会失败,那么你应该赞成。 毕竟,构造exception(包括其相关的回溯)需要时间。

例外情况应该用于:

  1. 意想不到的事情,或…
  2. 你需要跳过多于一个逻辑层次的事情(例如, break不够多),或者…
  3. 事情你不知道什么是要提前处理例外,或…
  4. 事先检查失败的东西是昂贵的(相对于只是尝试操作)

请注意,通常情况下,真正的答案是“既不” – 例如,在第一个示例中,您应该做的只是使用.get()来提供默认值:

 x = myDict.get('ABC', 'NO_ABC') 

如果有任何可能的比赛条件,应该使用tryexcept直接而不是内部。 例如,如果你想确保一个目录存在,不要这样做:

 import os, sys if not os.path.isdir('foo'): try: os.mkdir('foo') except OSError, e print e sys.exit(1) 

如果另一个线程或进程在isdirmkdir之间创build目录,则会退出。 相反,这样做:

 import os, sys, errno try: os.mkdir('foo') except OSError, e if e.errno != errno.EEXIST: print e sys.exit(1) 

只有当'foo'目录不能创build时才会退出。

应该使用一个try而不是一个if被解释为一个错误地传递的错误? 如果是这样,你是否明确地使用这种方式来消除它,所以它可以吗?

使用try是承认错误可能会通过,这是相反的,它通过默默。 使用except导致它不能通过。

使用try: except:if: else:逻辑比较复杂的情况下更好。 简单胜于复杂; 复杂比复杂好; 请求宽恕比容许更容易。

什么“错误不应该默默地传递”是警告,代码是否可以引发你所知道的exception,以及你的devise承认了这种可能性的情况,但是你没有devise出处理exception的方法。 在我看来,明确地沉默一个错误,就是做一个类似于pass一个except块的东西,这只能通过理解“无所事事”确实是在特定情况下正确的error handling来完成。 (这是几次我觉得在写好代码的评论可能真的需要的时候。

但是,在您的具体示例中,两者都不合适:

 x = myDict.get('ABC', 'NO_ABC') 

每个人都在指出这一点 – 即使你承认你一般的理解欲望,无法提供一个更好的例子 – 在相当多的情况下实际上存在着相同的边际步骤,寻找它们是解决问题的第一步。

正如其他post所说,这取决于情况。 使用try /有几个危险,除了提前检查数据的有效性,特别是在大型项目中使用时。

  • try块中的代码可能有机会在exception被捕获之前发生各种各样的破坏 – 如果你事先用if语句预先检查,你可以避免这种情况。
  • 如果在你的try块中调用的代码引发了一个常见的exceptiontypes,比如TypeError或者ValueError,那么你可能实际上并没有捕获到你期望捕获的同样的exception – 甚至可能在别人之前或之后引发同样的exception类可能会引发exception的行。

例如,假设你有:

 try: x = my_list[index_list[3]] except IndexError: x = 'NO_ABC' 

IndexError没有说明是否在尝试获取index_list或my_list的元素时发生。

对于一般的含义,你可以考虑阅读Python中的习语和反习语:例外 。

正如其他人所说,在你的特定情况下,你应该使用dict.get()

get(key [,default])

如果键在字典中,则返回键的值,否则返回默认值。 如果没有给出默认值,它默认为None,所以这个方法永远不会引发KeyError。