最佳实践似乎是使用 assert
对于如果代码正确则永远不会发生的条件,以及对于有点不寻常但可能发生的条件的异常(例如,当内存耗尽,或用户输入无效,或外部连接损坏)。我对这种做法背后的基本原理的理解如下:
assert
将通过 -O 解释器标志禁用。外部因素可能产生的状况决不能被忽视,因此断言存在是不恰当的。 OTOH,只有在我的代码不正确时才可能出现的情况希望通过测试和调试来消除,所以assert
没问题。assert
阻止调用者处理异常,因为AssertionError
通常被解释为“别捕获我,这是灾难性的失败”。此外,它太笼统,难以捕捉。当发现错误时这是完美的;典型的处理方法是停止执行并调试代码。如果是由于外部原因导致的常见情况那就不好了。
假设我编写一些代码,确保某个函数参数始终为正。如果我发现它是负数,显然我在代码中犯了错误。因此,我将断言
该论证是肯定的。
后来,有人发现这个函数在另一个应用程序中很有用。他们导入它,并向其发送各种数据。现在从我的函数的角度来看,收到负值实际上很有可能;这只是一个无效的用户输入。可以说,assert
不再合适,应该用异常替换。
由于几乎任何代码有一天都可能被重用,而且通常是在我不知情的情况下,所以这个论点似乎在说“永远不要使用 assert
;只使用异常”。显然,这不是一种可接受的做法。我错过了什么?
编辑:
更具体地说,假设该函数根本无法处理负参数。因此,一旦参数为负数,该函数将执行以下操作之一:
- 提出异常
- 断言失败
- 继续执行,可能会产生不正确的输出
我可以看到如果调用者捕获到负参数该多好。但是,如果对函数的调用散布在代码周围的几十个地方,那么由于多次重复相同的检查,可能会损害代码的清晰度。 (更不用说,它可能会被意外忘记。)
最佳答案
如果您正在编写/重用的函数对于正数或负数有效,则它不是应该包含断言的方法。调用重用函数的函数应该有断言,因为它是向函数提供无效值的函数。
function x() {
var i;
// logic to set i. use assertion to test the logic.
assert(i > 0);
reusedFunc(i);
}
如果reusedFunc(i)对于负数无效,则在传递负值时应该抛出异常。
关于Python断言语句和代码可重用性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10019043/