带有和不带括号的python断言


104

这是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")

请注意,最后一个不会引发错误。调用带或不带括号的assert导致此行为之间有什么区别?我的做法是使用括号,但以上内容表明我不应该这样做。


感谢您的帮助。关键字和内置函数之间的区别似乎很微妙。以下是我认为应该省略的关键字列表:docs.python.org/reference/lexical_analysis.html#keywords
gaefan 2010年

2
一个区别是您可以重新定义内置函数,但不能使用关键字来重新定义(不是前者是个好主意)。
盖凡

不是函数与关键字的区别,而是函数调用语句的区别。(例如,print以前是一个声明,并且没有括号)。
Tomasz Gandor

Answers:


129

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

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


10
之所以不会发生,assert (1==2)是因为单个表达式的括号不会自动创建一个元组;如果这样做,您将获得与#4相同的行为assert (1==2,)。如果您不这样做print ('foo', 'bar'),也会发生同样的事情print 'foo', 'bar';您会看到输出的元组
Michael Mrozek 2010年

值得进一步强调的是,这种形式的陈述assert(test, message)可能是错误的,并且肯定会造成混淆。不行!
tcarobruce

19
那么,缩进较长的assert语句的正确方法是WRT PEP8?似乎不可能。
stantonk


30

如果因为需要多行断言而将括号放在此处,则另一种方法是在行的末尾添加反斜杠,如下所示:

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

印刷品:

AssertionError: "derp should be 8, it is 7

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

我认为python的思想是程序应该自行更正,而不必担心打开断言的特殊标志。关闭断言的诱惑太大,因此已被弃用。

令我烦恼的是,assert相对于所有其他python编程构造,python 具有唯一的语法,并且此语法再次从python2更改为python3,又从python 3.4更改为3.6。使断言语句从任何版本到任何其他版本都不向后兼容。

assert是三级公民的肩膀,它将在python4中完全删除,当然在Python 8.1中也将完全删除。


2
是否有关于应使用什么而不是断言的文档?断言似乎是用于验证的逻辑名称,并且具有所需的行为,例如,在出错时显示特殊消息。
AnneTheAgile

18

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中的函数-它是关键字。


13

您可以不\这样来破坏assert语句:

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'
)

1
有趣的主意。我讨厌反斜杠的延续,这是将断言包装在实用程序函数中的替代方法(这是我的解决方案)。
Tomasz Gandor

1

以下是python doc中引用的内容

声明语句是将调试声明插入程序的便捷方法:

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

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

扩展形式,断言expression1,expression2等效于 if __debug__: if not expression1: raise AssertionError(expression2)

因此,当您在此处使用括号时,您使用的是简单形式,并且该表达式被评估为元组,当转换为布尔值时始终为True

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.