带括号和不带括号的python断言

Posted

技术标签:

【中文标题】带括号和不带括号的python断言【英文标题】:python assert with and without parenthesis 【发布时间】:2011-03-07 22:21:20 【问题描述】:

这里有四个简单的 assert 调用:

>>> assert 1==2
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AssertionError

>>> assert 1==2, "hi"
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AssertionError: hi

>>> assert(1==2)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AssertionError

>>> assert(1==2, "hi")

请注意,最后一个不会引发错误。带或不带括号调用断言导致此行为有什么区别?我的做法是使用括号,但上面建议我不应该。

【问题讨论】:

感谢您提供有用的答案。关键字和内置函数之间的区别似乎很微妙。这是一个关键字列表,我认为应该省略括号:docs.python.org/reference/lexical_analysis.html#keywords 一个区别是您可以重新定义内置函数,但不能使用关键字(不是前者是个好主意)。 不是函数和关键字的区别,而是函数调用 vs 语句。 (例如 - print 曾经是一个语句,并且没有括号)。 【参考方案1】:

如果您通过完整的解释器而不是通过 IDLE 运行最后一个 assert,则会给您一个警告 (SyntaxWarning: assertion is always true, perhaps remove parentheses?)。因为assert 是关键字而不是函数,所以您实际上是在传递一个元组作为第一个参数而省略了第二个参数。

回想一下,非空元组的计算结果为 True,并且由于断言消息是可选的,因此您在编写 assert(1==2, "hi") 时实际上调用了 assert True

【讨论】:

assert (1==2) 不会发生的原因是单个表达式周围的括号不会自动创建元组;如果您执行assert (1==2,),您将获得与#4 相同的行为。如果您使用print ('foo', 'bar') 而不是print 'foo', 'bar',也会发生同样的事情;你会看到输出的元组 值得进一步强调assert(test, message) 形式的陈述可能是错误的,而且肯定会令人困惑。没有括号! 那么,缩进长断言语句的正确方法是什么?佩普8?似乎不可能。 ***.com/questions/16065482/…【参考方案2】:

如果你把括号放在那里是因为你想要一个多行断言,那么另一种方法是在行尾放一个反斜杠,如下所示:

foo = 7
assert foo == 8, \
    "derp should be 8, it is " + str(foo)

打印:

AssertionError: "derp should be 8, it is 7

为什么这个 python assert 必须与其他所有东西不同:

我认为 Python 的意识形态是程序应该自我纠正,而不必担心打开断言的特殊标志。关闭断言的诱惑太大了,因此它被弃用了。

我与您一样烦恼,python assert 相对于所有其他 python 编程结构具有独特的语法,并且该语法再次从 python2 更改为 python3 并再次从 python 3.4 更改为 3.6。 使断言语句不能从任何版本向后兼容到任何其他版本。

assert 是三等公民,这是一个轻拍,它将在 python4 中完全删除,在 Python 8.1 中肯定会再次删除。

【讨论】:

是否有关于我们应该使用什么而不是断言的文档? Assert 似乎是一个用于验证的逻辑名称,并且它具有所需的行为,例如在出错时显示特殊消息。【参考方案3】:

您可以像这样在没有\ 的情况下中断断言语句:

foo = 7
assert foo == 8, (
    'derp should be 8, it is ' + str(foo))

或者如果您有更长的消息:

foo = 7
assert foo == 8, (
    'Lorem Ipsum is simply dummy text of the printing and typesetting '
    'industry. Lorem Ipsum has been the industry\'s standard dummy text '
    'ever since the 1500s'
)

【讨论】:

有趣的想法。我讨厌继续使用反斜杠,这是将断言包装在实用函数中的替代方法(这是我的解决方案)。【参考方案4】:

assert 1==2, "hi" 被解析为assert 1==2, "hi",其中“hi”作为关键字的第二个参数。因此为什么它正确地给出了一个错误。

assert(1==2) 被解析为assert (1==2),这与assert 1==2 相同,因为围绕单个项目的括号不会创建元组,除非有尾随逗号,例如(1==2,).

assert(1==2, "hi") 被解析为assert (1==2, "hi"),它不会给出错误,因为非空元组(False, "hi") 不是假值,并且没有为关键字提供第二个参数。

您不应该使用括号,因为assert 在 Python 中不是一个函数 - 它是一个关键字。

【讨论】:

【参考方案5】:

以下引用自python doc

断言语句是将调试断言插入程序的便捷方式:

assert_stmt ::= "assert" expression ["," expression]

简单的形式,断言表达式,等价于 if __debug__: if not expression: raise AssertionError

扩展形式assert expression1, expression2等价于 if __debug__: if not expression1: raise AssertionError(expression2)

因此,当您在这里使用括号时,您使用的是简单形式,并且表达式被评估为一个元组,当转换为 bool 时始终为 True

【讨论】:

以上是关于带括号和不带括号的python断言的主要内容,如果未能解决你的问题,请参考以下文章

Python调用函数带括号和不带括号的区别

python装饰器带括号和不带括号的语法和用法

为啥带括号和不带括号的 UNION ALL 表现不同?

Python调用函数加括号和不加括号的区别

Python调用函数加括号和不加括号的区别

JavaScript 函数调用时带括号和不带括号的区别