4

如果我在编写一些代码时不确定某事,我会尝试再次阅读The Zen of Python。这一次,那些台词让我犹豫了。

Errors should never pass silently.
Unless explicitly silenced.

在当前代码中,我有一些可能如下所示的函数:

def add_v_1(a, b):
    return a + b 

所有对他们的要求如下:

c = add_v_1(7, [])

此类代码的异常将冒泡并在上层捕获。

但应该是这样吗?

add_v_1可以引发TypeError异常,我想从中恢复。因此,可能的函数调用将是:

try:
    c = add_v_1(7, [])
except TypeError:
    print "Incorrect types!"

但是对于每次调用,我都应该进行异常处理。看起来很重。

所以,我可以这样做:

def add_v_2(a, b):
    try:
        return a + b
    except TypeError:
        print "Incorrect types!"

一个电话是:

c = add_v_2(7, [])

看起来更干净。

似乎所有这些方法都遵循The Zen of Python但其中哪一种是更好的选择?

4

3 回答 3

3

参考您的示例,您是否应该在函数内捕获异常是有争议的。这样做会None从函数返回,然后调用代码会检查函数的返回值,并将None其视为错误。它有效地用错误检查代替了异常处理。前者通常更 Pythonic。

您应该询问捕获错误是否有意义,例如尝试添加 2 种完全不同的数据类型。在这种情况下这样做似乎是一个编程错误,而不是您在正常执行期间所期望的那种事情。

你能做些什么来处理这样的错误?在函数的预期输出域内似乎没有任何有用的值可以返回......除了None表示无法产生结果之外。但是调用代码仍然必须执行某种错误检查......所以它还不如只处理一个异常 - 至少它只需要处理一次。

但是这个例子是人为的,很难给出笼统的建议。在这种特殊情况下,出于上述原因,我将允许异常传播到调用代码并在那里处理它。

于 2016-02-29T09:02:06.267 回答
2

当你能够从中恢复时,你应该处理它。如果您尝试添加两个类型不兼容的值,则无法从中恢复(没有进一步的上下文)。

假设您编写了一个 IntegerWrapper 类,并且您的函数“add_v_2”通常应该尝试连接两个值。

def add_v_2(a, b):
    try:
        return a + b
    except TypeError as e:
        if isinstance(a, IntegerWrapper):
            return str(a) + b
        else:
            print("I dont know how to handle this type: " + type(a).__name__)
            # reraise the error so the caller can handle it
            raise

这将尝试从a“错误类型”中恢复,但如果您知道如何从中恢复。如果它不知道(a 是另一种类型),它会重新引发异常,因此知道如何处理的人会看到错误。

(当然该实现包含错误,它并不意味着是一个“好的实现”)

于 2016-02-29T09:32:03.627 回答
0

输入:

def add_v_2(a, b):
    try:
        return a + b
    except Exception as e:
        print str(e)
c = add_v_2(7, [])
print (c)

输出:

unsupported operand type(s) for +: 'int' and 'list'
None
于 2016-02-29T08:18:37.913 回答