python的设计:为什么断言声明而不是函数?

cbe*_*zan 54 python assert language-design

在Python中,assert是一个语句,而不是一个函数.这是一个刻意的决定吗?assert成为一个声明(和保留字)而不是一个函数有什么好处吗?

根据 文件,assert expression1, expression2扩大到

if __debug__:
    if not expression1: raise AssertionError(expression2)
Run Code Online (Sandbox Code Playgroud)

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

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

assert(some_long_condition,
       "explanation")
Run Code Online (Sandbox Code Playgroud)

但因为assert是一个声明,元组总是评估True,你得到

SyntaxWarning: assertion is always true, perhaps remove parentheses?
Run Code Online (Sandbox Code Playgroud)

写它的正确方法是

assert some_long_condition, \
       "explanation"
Run Code Online (Sandbox Code Playgroud)

这可能不那么漂亮了.

vla*_*adr 34

断言是声明(和保留字)而不是函数有什么好处吗?

  1. 无法重新分配给用户函数,这意味着它可以在编译时被有效禁用,如@mgilson指出的那样.
  2. 第二个可选参数的评估将推迟到断言失败时为止/何时.使用函数和函数参数(需要传递lambda)很难做到这一点.不推迟第二个参数的评估会引入额外的开销.

  • 我没有想到你提出的第二点(明白了吗?提出了?因为断言`raise AssertionError`?)。+1。 (2认同)
  • 只是想再补充一点,正如我在另一个答案中提到的:它不仅推迟了第二个可选参数。第一个参数也被延迟,因此只有在调试模式下才会对其进行评估 (2认同)

mgi*_*son 17

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


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


Adr*_*hum 7

我不是Python的专家,但我相信性能是最重要的原因之一.

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

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


sie*_*z0r 7

除了其他答案(和一些偏离主题)的提示.为避免使用反斜杠,可以在括号内使用隐式线连接.;-)

代替:

assert some_long_condition, \
       "explanation"
Run Code Online (Sandbox Code Playgroud)

你可以写:

assert some_long_condition, (
       "explanation")
Run Code Online (Sandbox Code Playgroud)