簡體   English   中英

引發異常與返回在函數中無?

[英]Raise exception vs. return None in functions?

在Python中的用戶定義函數中,更好的做法是: raise異常或return None 例如,我有一個在文件夾中查找最新文件的函數。

def latestpdf(folder):
    # list the files and sort them
    try:
        latest = files[-1]
    except IndexError:
        # Folder is empty.
        return None  # One possibility
        raise FileNotFoundError()  # Alternative
    else:
        return somefunc(latest)  # In my case, somefunc parses the filename

另一個選擇是保留異常並在調用者代碼中處理它,但我認為處理FileNotFoundErrorIndexError更清楚。 還是用其他名稱重新引發異常是不好的形式嗎?

這實際上是語義問題。 foo = latestpdf(d) 什么意思

沒有最新文件完全合理嗎? 然后確定,只返回None。

您是否希望總是找到最新文件? 引發異常。 是的,重新提出一個更合適的例外是可以的。

如果這只是應該應用於任何目錄的通用函數,我將做一個前一個並返回None。 如果該目錄是(例如)要成為包含應用程序已知文件集的特定數據目錄,則將引發異常。

在回答您的問題之前,我會提出一些建議,因為它可能會為您解答。

  • 始終以描述性方式命名您的函數。 對任何人來說, latestpdf幾乎沒有什么意義,但查看您的函數latestpdf()可獲得最新的pdf。 我建議您將其命名為getLatestPdfFromFolder(folder)

一旦我這樣做,就清楚應該返回什么內容。如果沒有pdf,則會引發異常。 但是,在那里等待更多..

  • 明確定義功能。 由於尚不清楚somefuc應該做什么,而且(顯然)它與獲取最新pdf的關系也不明顯,因此建議您將其刪除。 這使代碼更具可讀性。

for folder in folders:
   try:
       latest = getLatestPdfFromFolder(folder)
       results = somefuc(latest)
   except IOError: pass

希望這可以幫助!

我通常更喜歡在內部處理異常(即在被調用函數內部進行try / except,可能返回None),因為python是動態類型的。 總的來說,我認為這是一種判斷調用方式,但是在動態類型的語言中,有一些小因素會提示擴展規模,以免將異常傳遞給調用者:

  1. 不會向任何調用您函數的人通知可能引發的異常。 知道您正在尋找什么樣的異常(以及應該避免的一般性例外),成為一種藝術形式。
  2. if val is None則比except ComplicatedCustomExceptionThatHadToBeImportedFromSomeNameSpace 嚴重的是,我討厭不得不記住from django.core.exceptions import ObjectDoesNotExist鍵入內容from django.core.exceptions import ObjectDoesNotExist在所有django文件的頂部都from django.core.exceptions import ObjectDoesNotExist只是為了處理一個非常普通的用例。 在靜態類型的世界中,讓編輯器為您完成。

不過,老實說,它始終是一個判斷調用,而您所描述的情況(被調用函數收到它無法幫助的錯誤)是重新引發有意義的異常的極好理由。 您有完全正確的想法,但除非有例外,否則您將在堆棧跟蹤中提供比

AttributeError: 'NoneType' object has no attribute 'foo'

如果您返回未處理的None(無),則打擾者將看到呼叫的結果,十分之九。

(所有這些使我希望python異常在默認情況下具有cause屬性,就像在Java中一樣,它使您可以將異常傳遞到新的異常中,以便您可以拋棄所有想要的問題,而不會丟失問題的原始源。

一般來說,如果發生了無法恢復的災難性事件(即,您的函數處理了無法連接的某些互聯網資源),則應該拋出異常;如果函數確實返回了某些內容,則應返回None。但沒有合適的返回值(例如,如果您的函數嘗試匹配字符串中的子字符串,則為“ None”)。

使用python 3.5的輸入

返回None時的示例函數為:

def latestpdf(folder: str) -> Union[str, None]

並且在引發異常時將是:

def latestpdf(folder: str) -> str 

選項2似乎更具可讀性和pythonic

(+選項,如前所述,為異常添加注釋。)

暫無
暫無

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

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