引发exception与返回在Python函数中无

在Python中的用户定义函数中有什么更好的做法:抛出exception或返回None? 例如,我有一个函数可以find文件夹中最近的文件。

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 

另一个select是留下exception,并在调用者代码中处理它,但我认为处理FileNotFoundError比IndexError更清楚。 或者用不同的名字重新引发exception是不好的方式?

这确实是一个语义问题。 foo = latestpdf(d) 什么意思

没有最新的文件是完全合理的吗? 那么确定,只是返回None。

你期望总是find最新的文件? 引发exception。 是的,重新提出一个更合适的例外是好的。

如果这只是一个适用于任何目录的通用函数,我会做前者并返回None。 如果这个目录例如是一个包含应用程序已知文件集的特定数据目录,那么我会引发一个exception。

在回答你的问题之前,我会提出一些build议,因为它可能会回答你的问题。

  • 始终将您的function命名为描述性的。 latestpdf对任何人都意味着什么,只是看你的functionlatestpdf()得到最新的PDF。 我build议你把它命名为getLatestPdfFromFolder(folder)

只要我这样做,它变得清楚它应该返回什么。如果没有PDF提出例外。 但是在那里等一下..

  • 保持清晰的function。 由于它不是什么明显的somefuc应该做的,它不是(显然)是如何与获得最新的pdf相关,我build议你把它移出。 这使得代码更具可读性。

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

希望这可以帮助!

我通常更喜欢内部处理exception(即尝试/除了被调用的函数内,可能返回一个None),因为python是dynamictypes的。 一般来说,我认为这是一种判断方式,但是在dynamictypes语言中,有一些小的因素会导致规模不足,而不会将exception传递给调用者:

  1. 任何人调用你的函数都不会被通知可以抛出的exception。 这是一种艺术forms,知道你寻找什么样的exception(除了块应该避免通用)。
  2. if val is None则比except ComplicatedCustomExceptionThatHadToBeImportedFromSomeNameSpace 。 严重的是,我讨厌不得不记得from django.core.exceptions import ObjectDoesNotExist在我所有的Django文件的顶部,以处理一个非常常见的用例。 在一个静态types的世界里,让编辑为你做。

老实说,这总是一个判断的调用,而你所描述的情况,被调用的函数接收到的错误是无法帮助的,这是重新提出有意义的exception的一个很好的理由。 你有完全正确的想法,但除非你是个例外,否则会在堆栈跟踪中提供更有意义的信息

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

如果你返回一个没有处理的无,那么十个中的九个是主叫方会看到的,不要麻烦。

(所有这一切都使我希望pythonexception在默认情况下具有cause属性,就像在java中一样,它允许您将exception传递到新的exception中,以便您可以重新引发所有您想要的并且永远不会丢失问题的原始来源。

一般来说,如果发生了无法恢复的灾难性事件(即,您的函数处理某些无法连接的Internet资源),则应该抛出exception,并且如果您的函数真的应该返回但是没有什么东西可以用来返回(例如,如果你的函数试图匹配一个string中的子string,那么就是“None”)。