65

在 Python 中,assert是一个语句,而不是一个函数。这是一个深思熟虑的决定吗?assert有一个语句(和保留字)而不是一个函数有什么好处吗?

根据文档,扩展 assert expression1, expression2

if __debug__:
    if not expression1: raise AssertionError(expression2)

文档还说“当在编译时请求优化时,当前的代码生成器不会为断言语句发出代码。” 在不知道细节的情况下,似乎需要一个特殊情况才能使这成为可能。但是,一种特殊情况也可用于优化对assert()函数的调用。

如果assert是一个函数,你可以写:

assert(some_long_condition,
       "explanation")

但是因为assert是一个语句,元组总是计算为True,你得到

SyntaxWarning: assertion is always true, perhaps remove parentheses?

正确的写法是

assert some_long_condition, \
       "explanation"

这可以说是不那么漂亮。

4

4 回答 4

39

让 assert 成为语句(和保留字)而不是函数有什么好处吗?

  1. 不能重新分配给用户函数,这意味着它可以在编译时被有效地禁用,正如@mgilson 指出的那样。
  2. 第二个可选参数的评估被推迟到如果/当断言失败时。用函数和函数参数来做这件事很尴尬(需要传递一个 lambda)。不推迟对第二个参数的评估会带来额外的开销。
于 2012-11-15T02:20:53.010 回答
20

在 python 和其他语言(特别是 C)中,一个美妙的事情assert是您可以删除它们以优化您的代码,只需添加正确的#define(可选地在命令行上使用我曾经使用过的任何编译器)或优化标志(-O在Python)。如果assert成为一个函数,这个特性将不可能添加到 python,因为直到运行时你才知道你是否有assert同名的内置函数或用户定义的函数。


另请注意,在 python 中,函数调用相当昂贵。用代码替换内联if __debug__: ...可能比执行函数调用更有效,如果您将assert语句放在性能关键例程中,这可能很重要。

于 2012-11-15T02:16:20.570 回答
10

除了其他答案(和某种题外话)之外,还有一个提示。为避免使用反斜杠,您可以在括号内使用隐式行连接。;-)

代替:

assert some_long_condition, \
       "explanation"

你可以写:

assert some_long_condition, (
       "explanation")
于 2013-10-01T06:54:24.370 回答
8

我不是 Python 专家,但我相信性能是最大的原因之一。

如果我们有 assert(expression, explain) 作为函数,如果表达式的计算成本很高,即使我们处于非调试模式,Python 也需要计算两个表达式才能将其传递给 assert 函数。

通过扩展断言,表达式和解释语句实际上不会被评估,除非它们确实需要(当调试评估为真时)。我认为,如果我们想在不必要的时候断言不影响性能(即生产系统中没有性能影响),这一点至关重要。

于 2012-11-15T03:36:18.057 回答