python中关于错误与成功的返回值的最佳实践

Tal*_*aul 48 python return

一般的,假设你有一个像下面的方法.

def intersect_two_lists(self, list1, list2):
    if not list1:
        self.trap_error("union_two_lists: list1 must not be empty.")
        return False
    if not list2:
        self.trap_error("union_two_lists: list2 must not be empty.")
        return False
    #http://bytes.com/topic/python/answers/19083-standard
    return filter(lambda x:x in list1,list2)
Run Code Online (Sandbox Code Playgroud)

在这个特殊的方法中,当发现错误时,我不想在这种情况下返回空列表,因为这可能是这个特定方法调用的真正答案,我想返回一些东西来指示参数不正确.所以我在这种情况下错误地返回False,否则返回一个列表(空或不).

我的问题是,在这样的领域中最好的做法是什么,而不仅仅是列表?返回我想要的任何东西,并确保我记录下来供用户阅读?:-)你们大多数人都做了什么:

  1. 如果成功,你应该返回True或False,你会发现错误?
  2. 如果成功,你应该返回一个列表,你会发现错误?
  3. 如果成功,你应该返回一个文件句柄,你会发现错误?
  4. 等等

Nad*_*mli 59

首先,无论你做什么都不会返回结果和错误消息.这是处理错误的一种非常糟糕的方法,会让你无休止的头痛.如果需要指示错误,则始终引发异常.

除非有必要,否则我通常倾向于避免提出错误.在您的示例中,实际上不需要抛出错误.将空列表与非空列表相交并不是错误.结果只是空列表,这是正确的.但是,假设你想处理其他案件.例如,如果方法获得非列表类型.在这种情况下,最好提出异常.例外是没有什么可害怕的.

我的建议是查看Python库中的类似函数,看看Python如何处理这些特殊情况.例如,看看集合中的交集方法,它往往是宽容的.在这里,我试图将空集与空列表相交:

>>> b = []
>>> a = set()
>>> a.intersection(b)
set([])

>>> b = [1, 2]
>>> a = set([1, 3])
>>> a.intersection(b)
set([1])
Run Code Online (Sandbox Code Playgroud)

只在需要时抛出错误:

>>> b = 1
>>> a.intersection(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
Run Code Online (Sandbox Code Playgroud)

当然,有些情况下,成功或失败时返回真或假可能是好的.但要保持一致非常重要.该函数应始终返回相同的类型或结构.拥有一个可以返回列表或布尔值的函数是非常令人困惑的.或者返回相同的类型,但是如果出现错误,该值的含义可能不同.

编辑:

OP说:

我想返回一些东西来表明参数不正确.

没有什么比异常更好的错误了.如果要指示参数不正确,请使用异常并输入有用的错误消息.在这种情况下返回结果只是令人困惑.在其他情况下,您可能希望指出没有发生任何事情,但这不是错误.例如,如果您有一个方法从表中删除条目,并且请求删除的条目不存在.在这种情况下,成功或失败时返回True或False可能没问题.这取决于应用程序和预期的行为

  • +1:从可用性的角度来看,返回一致的结果绝对是一个要求。 (2认同)

Joh*_*ica 21

提出异常比返回特殊值更好.这正是异常的设计目的,用更健壮和结构化的错误处理机制替换错误代码.

class IntersectException(Exception):
    def __init__(self, msg):
        self.msg = msg
    def __str__(self):
        return self.msg

def intersect_two_lists(self, list1, list2):
    if not list1: raise IntersectException("list1 must not be empty.")
    if not list2: raise IntersectException("list2 must not be empty.")

    #http://bytes.com/topic/python/answers/19083-standard
    return filter(lambda x:x in list1,list2)
Run Code Online (Sandbox Code Playgroud)

在这种特殊情况下,我可能只是放弃测试.真的,交叉空列表没有错.lambda这些天也有点沮丧,而不是列表理解.请参阅查找两个列表的交集?有几种方法可以不使用而编写lambda.

  • 尽管如此,这并不能真正测试空列表.考虑调用`intersect_two_lists(0,0)`或`intersect_two_lists('',None)`.它们都是不正确的,但异常会说``list1`在它甚至不是正确的类型时都是空的. (2认同)
  • 你是对的,这不是专门检查空列表,但原始代码也没有.Python样式更多的是继续使用对象而不是事先烦恼它是否是特定类型. (2认同)

jld*_*ont 13

我想返回一个元组:

(是的,some_result)

(False,some_useful_response)

所述some_useful_response对象可用于处理返回条件或可用于显示调试信息.

注意:此技术适用于任何类型的返回值.它不应该与异常情况混淆.

在接收端,您只需要解压缩:

代码,响应= some_function(...)

此技术适用于"正常"控制流:当发生某些意外输入/处理时,必须使用异常功能.

另外值得注意的是:这种技术有助于规范化函数返回.程序员和功能的用户都知道会发生什么.

免责声明:我来自Erlang背景:-)

  • 我无法相信这是受到鼓励的.使用错误代码是一场设计梦魇.查看Ned的文章了解更多详情:http://nedbatchelder.com/text/exceptions-vs-status.html (4认同)
  • @nadia:返回元组是另一种方法,也是一种非常有效的方法.许多"异常与状态"参数都是特定于语言的,这些语言很难返回多个东西并捕获结果 - 即,你不能做什么`status,result = f()`而且你被迫做像`result = f(&status);`来实现同样的事情.元组是Python中的第一类类型,所以我们不妨使用它们.如果在整个API中一致地完成,那么它非常优雅和高效. (2认同)

Ned*_*der 11

例外肯定比状态返回更好(和更多Pythonic).有关此问题的更多信息:例外与状态回报