cho*_*own 125 python if-statement exception-handling try-catch pep
我应该测试if
某些东西是有效的还是只是try
为了捕获异常?
例如,我应该:
if len(my_list) >= 4:
x = my_list[3]
else:
x = 'NO_ABC'
Run Code Online (Sandbox Code Playgroud)
要么:
try:
x = my_list[3]
except IndexError:
x = 'NO_ABC'
Run Code Online (Sandbox Code Playgroud)
一些想法......
PEP 20说:
错误不应该默默地传递.
除非明确沉默.
应该使用a try
而不是if
被解释为默认传递的错误?如果是这样,你是否通过这种方式使用它来明确地对它进行静音,从而使它成为可能?
我不是指的情况下,你只能做的事情1路; 例如:
try:
import foo
except ImportError:
import baz
Run Code Online (Sandbox Code Playgroud)
Rem*_*emi 149
你应该更喜欢try/except
,if/else
如果这导致
通常,这些都是相辅相成的.
速度起坐
在尝试通过以下方式在长列表中查找元素的情况下:
try:
x = my_list[index]
except IndexError:
x = 'NO_ABC'
Run Code Online (Sandbox Code Playgroud)
try,除了是index
可能在列表中并且通常不会引发IndexError 的最佳选项.这样您就可以避免额外查找if index < len(mylist)
.
Python鼓励使用异常,你处理的是Dive Into Python中的一个短语.您的示例不仅处理异常(优雅地),而不是让它以静默方式传递,而且只有在未找到索引的异常情况下才会发生异常(因此单词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)
Run Code Online (Sandbox Code Playgroud)
更好(EAFP:更容易请求宽恕而不是许可):
try:
return int(str)
except (TypeError, ValueError, OverflowError): #int conversion failed
return None
Run Code Online (Sandbox Code Playgroud)
dus*_*uff 19
在这种特殊情况下,您应该完全使用其他东西:
x = myDict.get("ABC", "NO_ABC")
Run Code Online (Sandbox Code Playgroud)
但是,一般情况下:如果您希望测试频繁失败,请使用if
.如果测试相对于仅尝试操作而言是昂贵的,并且如果失败则捕获异常,请使用try
.如果这些条件都不适用,请更容易阅读.
如果存在任何竞争条件,应始终使用try
并且except
直接在if
防护装置内部使用.例如,如果要确保存在目录,请不要这样做:
import os, sys
if not os.path.isdir('foo'):
try:
os.mkdir('foo')
except OSError, e
print e
sys.exit(1)
Run Code Online (Sandbox Code Playgroud)
如果另一个线程或进程在isdir
和之间创建目录mkdir
,则退出.相反,这样做:
import os, sys, errno
try:
os.mkdir('foo')
except OSError, e
if e.errno != errno.EEXIST:
print e
sys.exit(1)
Run Code Online (Sandbox Code Playgroud)
只有在无法创建'foo'目录时才会退出.
如果在你做之前检查某些东西是否会失败是微不足道的,你应该赞成这一点.毕竟,构造异常(包括其相关的追溯)需要时间.
例外情况应该用于:
break
不能让你足够远),或......请注意,通常情况下,真正的答案是"不" - 例如,在您的第一个示例中,您真正应该做的只是.get()
用来提供默认值:
x = myDict.get('ABC', 'NO_ABC')
Run Code Online (Sandbox Code Playgroud)
正如其他帖子所提到的,这取决于情况。使用 try/except 代替提前检查数据的有效性存在一些危险,尤其是在大型项目中使用它时。
例如,假设你有:
try:
x = my_list[index_list[3]]
except IndexError:
x = 'NO_ABC'
Run Code Online (Sandbox Code Playgroud)
IndexError 没有说明它是否在尝试获取 index_list 或 my_list 的元素时发生。