最佳实践似乎是使用assert
表示如果代码正确则不应该发生的条件,并且对于有点不寻常但可能发生的条件的异常(例如,当内存耗尽时) ,或用户输入无效,或外部连接中断)。我理解这种做法背后的理由如下:
assert
将被-O解释器标志禁用。不得忽视外部因素可能产生的条件,因此断言不合适。 OTOH,只有在我的代码不正确时才会出现的条件有望通过测试和调试消除,所以assert
没问题。
assert
不鼓励调用者处理异常,因为AssertionError
通常被解释为“不要抓住我,这是灾难性的失败”。此外,它太笼统了。当发现错误时,这是完美的;典型的处理方法是停止执行和调试代码。由于外部原因,这是一种常见的情况并不好。
假设我编写了一些代码,我确保某个函数参数始终为正。如果我发现它是否定的,显然我在代码中犯了一个错误。因此,我将assert
认为论证是积极的。
后来,有人发现此功能在另一个应用程序中很有用。他们导入它,并向其发送各种数据。现在从我的功能来看,接收负值实际上很可能;它只是一个无效的用户输入。可以说,assert
不再合适,应该替换为例外。
由于几乎任何代码都可能在某一天被重用,通常在我不知情的情况下,这个论点似乎说“从不使用assert
;只使用例外”。显然,这不是一种公认的做法。我错过了什么?
编辑:
更具体地说,假设该函数根本无法处理负参数。因此,一旦参数为负,该函数将执行以下操作之一:
我可以看到如果调用者捕获到负面参数会有多好处。但是如果对函数的调用散布在代码周围的许多地方,那么由于同一检查的多次重复,它可能会对代码清晰度产生不利影响。 (更不用说,它可能会被意外遗忘。)
答案 0 :(得分:2)
如果您正在编写/重用的函数对正数或负数有效,则不应该包含断言的方法。调用重用函数的函数应该有断言,因为它是为函数提供无效值的函数。
function x() {
var i;
// logic to set i. use assertion to test the logic.
assert(i > 0);
reusedFunc(i);
}
如果reusedFunc(i)对负数无效,则在传递负值时应抛出异常。
答案 1 :(得分:1)
assert
语句用于开发和调试代码时使用的内容,而不是保证关键的API约束。
对于您的正数示例,如果在代码中使用负值会产生不良后果,请测试值并使用有用的错误消息引发ValueError
。
我告诉人们永远不要使用断言语句。它们很容易写,但它们往往不合适。
当人们编写长文并决定使用括号使语句和消息跨越多行时, assert
语句也会失败...这会在现代Python中生成一个关于元组的SyntaxWarning
作者无意中通过在非函数语句中使用(condition,message)来创建,但它并不总是这样做。
另一个经验法则:如果你看到一个单元测试验证引发了AssertionError
,那么代码不应该使用断言。
如果你不使用assert
陈述,这些东西都不会咬你。