这个特殊的例子与Python中的Django有关,但应该适用于任何支持例外的语言:
try:
object = ModelClass.objects.get(search=value)
except DoesNotExist:
pass
if object:
# do stuff
Django模型类提供了一个简单的方法 get ,它允许我从数据库中搜索一个且只有一个对象,如果它发现或多或少它会引发一个例外。如果可以使用替代过滤器方法找到零或更多,则返回一个列表:
objects = ModelClass.objects.filter(search=value)
if len(objects) == 1:
object = objects[0]
# do stuff
我是否过度厌恶异常?对我而言,例外看起来有点浪费,猜测,四分之一到一半的时间将是“特殊”。我更喜欢在失败时返回 None 的函数。我会更好地使用Django的过滤器方法并自己处理列表吗?
答案 0 :(得分:9)
信不信由你,这实际上是每种语言都有所不同的问题。在Python中,对于语言本身并不例外的事件,会定期抛出异常。因此,我认为“你应该只在异常情况下抛出例外”规则并不十分适用。我认为你在这个论坛上得到的结果将倾向于这个观点,考虑到大量的.Net程序员(参见this question)了解更多信息。)
至少,我最好不要抓住那些坚持使用Python中的生成器或for循环的人(这两者都涉及在非特殊情况下抛出异常)。
答案 1 :(得分:7)
围绕使用异常,编程语言存在很大的分歧。
多数人认为例外应该是例外。在大多数具有例外的语言中,例如,通过例外转移控制比通过程序返回更加昂贵。
有一个强烈的少数观点认为异常只是另一种控制流构造,它们应该便宜。 Standard ML of New Jersey和Objective Caml编译器订阅该视图。如果你有便宜的例外,你可以用更难以使用其他机制进行干净编码的方式编写一些花哨的回溯算法。
我已经看过这个辩论多次重复新的语言设计,而且几乎总是,胜利者决定异常应该是昂贵和罕见的。当你关心表演时,你应该考虑到这一点,这是明智的。
答案 2 :(得分:5)
线索在名称中 - 例外应该是例外。
如果您总是希望该项目存在,那么请使用get
,但如果您认为它不存在合理比例的时间(即它不存在是预期结果而不是特殊结果)那么我建议使用filter
。
所以,当你指出预期不存在1比2和1比4之间时,我肯定会在filter
附近写一个包装器,因为这绝对不是特例。
答案 3 :(得分:2)
答案取决于代码的意图。 (我不确定你的代码示例是什么意思,特殊情况下的传递令人困惑,其余的代码将使用object
变量做什么?)
在许多情况下,是否使用例外或使用将案件视为非例外的方法是一种品味问题。当然,如果except子句中的实际代码与您必须使用的过滤器方法一样复杂,以避免异常,那么使用filter方法。更简单的代码是更好的代码。
答案 4 :(得分:2)
我同意另一个答案,但我想补充一下,这样的异常传递会给你带来非常明显的性能影响。强烈建议您检查结果是否存在(如果这是过滤器的作用),而不是传递异常。
编辑:
为响应对此的号码请求,我运行了这个简单的测试......
import time
def timethis(func, list, num):
st=time.time()
for i in xrange(0,1000000):
try:
func(list,num)
except:
pass
et = time.time()
print "Took %gs" % (et-st)
def check(list, num):
if num < len(list):
return list[num]
else:
return None
a=[1]
timethis(check, a, 1)
timethis(lambda x,y:x[y], a, 1)
输出是..
Took 0.772558s
Took 3.4512s
HTH。
答案 5 :(得分:2)
对冗余的厌恶是一个观点问题 - 然而,如果有理由相信一个函数或方法将被多次调用或被快速调用,异常将导致显着的减速。我从我的previous question中学到了这一点,我之前依赖于抛出的异常来返回默认值,而不是进行参数检查以返回默认值。
当然,异常仍然可以出于任何原因存在,并且您不应该害怕在必要时使用或抛出异常 - 特别是那些可能会破坏调用函数正常流量的异常。
答案 6 :(得分:2)
我不同意上述注释,在这种情况下异常效率低下,特别是因为它在I / O绑定操作中使用。
这是一个使用Django和内存中的sqlite数据库的更现实的例子。运行100个不同查询中的每一个,然后对100个运行中的每一个进行平均。虽然我怀疑它是否重要,但我也改变了执行顺序。
With ObjectDoesNotExist... 0.102783939838
Without exception ........ 0.105322141647
With ObjectDoesNotExist... 0.102762134075
Without exception ........ 0.101523952484
With ObjectDoesNotExist... 0.100004930496
Without exception ........ 0.107946784496
您可以在自己的Django环境中对此进行检测,但我怀疑您是否花时间避免此异常。