如果我在编写代码时不确定,我会再次尝试阅读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
,但其中哪一种是更好的选择?
答案 0 :(得分:3)
参考你的例子,你是否应该在函数内捕获异常是有争议的。这样做会从函数返回None
,然后通过检查函数的返回值来加重调用代码,并将None
视为错误。它通过错误检查有效地替换了异常处理。前者通常更像Pythonic。
您应该询问是否有必要捕获错误,例如尝试添加2个完全不同的数据类型。在这种情况下这样做似乎是一个编程错误,而不是在正常执行期间你期望的事情。
你能做些什么来处理这样的错误?似乎没有任何有用的值可以在函数的预期输出的域内返回...除了None
以外,表示无法生成结果。但是调用代码仍然必须执行某种错误检查...所以它也可以只处理异常 - 至少它只需处理一次。
但这个例子是人为的,很难给出全面的建议。在这种特殊情况下,由于上述原因,我会允许异常传播到调用代码并在那里处理它。
答案 1 :(得分: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是另一种类型)它会重新引用异常,所以知道如何处理它的人会看到错误。
(当然,该实现包含错误,它并不意味着是一个良好的实现")
答案 2 :(得分: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