Python断言语句和代码可重用性

时间:2012-04-04 20:50:58

标签: python exception python-3.x assert software-design

最佳实践似乎是使用assert表示如果代码正确则不应该发生的条件,并且对于有点不寻常但可能发生的条件的异常(例如,当内存耗尽时) ,或用户输入无效,或外部连接中断)。我理解这种做法背后的理由如下:

  1. assert将被-O解释器标志禁用。不得忽视外部因素可能产生的条件,因此断言不合适。 OTOH,只有在我的代码不正确时才会出现的条件有望通过测试和调试消除,所以assert没问题。

  2. assert不鼓励调用者处理异常,因为AssertionError通常被解释为“不要抓住我,这是灾难性的失败”。此外,它太笼统了。当发现错误时,这是​​完美的;典型的处理方法是停止执行和调试代码。由于外部原因,这是一种常见的情况并不好。

  3. 假设我编写了一些代码,我确保某个函数参数始终为正。如果我发现它是否定的,显然我在代码中犯了一个错误。因此,我将assert认为论证是积极的。

    后来,有人发现此功能在另一个应用程序中很有用。他们导入它,并向其发送各种数据。现在从我的功能来看,接收负值实际上很可能;它只是一个无效的用户输入。可以说,assert不再合适,应该替换为例外。

    由于几乎任何代码都可能在某一天被重用,通常在我不知情的情况下,这个论点似乎说“从不使用assert;只使用例外”。显然,这不是一种公认​​的做法。我错过了什么?

    编辑:

    更具体地说,假设该函数根本无法处理负参数。因此,一旦参数为负,该函数将执行以下操作之一:

    • 提出异常
    • 失败断言
    • 继续执行,可能会产生错误的输出

    我可以看到如果调用者捕获到负面参数会有多好处。但是如果对函数的调用散布在代码周围的许多地方,那么由于同一检查的多次重复,它可能会对代码清晰度产生不利影响。 (更不用说,它可能会被意外遗忘。)

2 个答案:

答案 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陈述,这些东西都不会咬你。