python的设计:为什么assert是一个语句而不是一个函数?

问题描述 投票:0回答:4

在Python中,

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"

为什么做出这个决定?使用

assert
作为语句(和 保留字)而不是函数有优势吗?

python language-design assert
4个回答
42
投票

使用断言作为语句(和保留字)而不是函数有什么优点吗?

  1. 无法重新分配给用户函数,这意味着它可以在编译时有效地禁用,正如 @mgilson 指出的那样。
  2. 第二个可选参数的评估被推迟,直到断言失败。使用函数和函数参数执行此操作很尴尬(需要传递 lambda。)不推迟第二个参数的计算会带来额外的开销。

21
投票

Python 和其他语言(特别是 C)中的

assert
的美妙之处之一是,您可以通过添加正确的
#define
来删除它们来优化代码(可选地在命令行上使用我曾经使用过的任何编译器)使用)或优化标志(Python 中的
-O
)。 如果
assert
成为一个函数,这个功能将无法添加到 python 中,因为直到运行时你才知道你是否有内置
assert
函数或同名的用户定义函数。


还要注意,在 python 中,函数调用的开销相当大。 用代码

if __debug__: ...
替换内联可能比执行函数调用更有效,如果您将
assert
语句放入性能关键例程中,这可能会很重要。


10
投票

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

代替:

assert some_long_condition, \
       "explanation"

你可以写:

assert some_long_condition, (
       "explanation")

8
投票

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.