簡體   English   中英

避免例外?

[英]Avoid exceptions?

此特定示例與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的filter方法並自己處理列表嗎?

信不信由你,這實際上是一個問題,每種語言都有所不同。 在Python中,通常會針對語言本身並非異常的事件引發異常。 因此,我認為“僅應在特殊情況下引發異常”規則並不適用。 考慮到大量的.Net程序員(請參閱此問題 )以獲取更多信息,我認為您在該論壇上獲得的結果將傾向於該觀點。

至少,我最好不要在Python中使用生成器或for循環來抓住那些堅持該規則的人(這兩者都涉及在非異常情況下引發異常)。

編程語言在使用異常方面有很大的分歧。

  • 大多數人認為例外應該是例外 例如,在大多數帶有例外的語言中,通過例外進行的控制轉移比通過過程返回進行的轉移要昂貴得多。

  • 少數派強烈認為例外是另一個控制流構造,它們應該便宜。 新澤西Standard MLObjective Caml編譯器都支持該視圖。 如果您有便宜的例外情況,則可以采用一些難以使用其他機制進行干凈編碼的方式來編寫一些奇特的回溯算法。

我已經看到針對新語言設計的辯論多次進行,並且幾乎總是贏家認為例外應該是昂貴且罕見的。 當您關心表現時,明智的做法是牢記這一點。

線索就是名字-例外應該是例外。

如果您始終希望該項目存在,請使用get ,但是如果您希望它在一段時間內不存在(即不存在是預期的結果,而不是例外的結果),則建議使用filter

因此,正如您所指出的那樣,期望不存在1比2和1比4之間的問題,我肯定會在filter周圍寫一個包裝filter ,因為這絕對不是例外。

答案將取決於代碼的意圖。 (我不確定您的代碼示例打算做什么,在特殊情況下的傳遞會造成混淆,其余代碼將如何與object變量一起使用?)

在許多情況下,是否使用例外或使用將案件視為非例外的方法都是一個問題。 當然,如果except子句中的實際代碼與為避免異常而必須使用的過濾器方法一樣復雜,請使用過濾器方法。 簡單的代碼就是更好的代碼。

我同意其他答案,但我想添加這樣的異常傳遞,這將給您帶來非常明顯的性能損失。 強烈建議您檢查結果是否存在(如果這是過濾器的作用),而不要傳遞異常。


編輯:

為了響應對此的要求,我進行了這個簡單的測試...

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。

厭惡排斥是一種意見問題-但是,如果有理由相信某個函數或方法將被多次調用或被快速調用,則異常將導致速度顯着下降。 我從上一個問題中學到了這一點,在該問題中 ,我以前依靠拋出的異常返回默認值,而不是通過參數檢查返回默認值。

當然,由於任何原因仍然可以存在異常,如果有必要,您不應該害怕使用或拋出異常-尤其是那些可能破壞調用函數正常流程的異常。

我不同意上面的評論,在這種情況下,異常是低效的,尤其是因為它是在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環境中對此進行檢測,但是我懷疑您的時間是否花在了避免此異常上。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM