带有和不带括号的python断言

问题:带有和不带括号的python断言

这是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导致此行为之间有什么区别?我的做法是使用括号,但以上内容表明我不应该这样做。

Here are four simple invocations of 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")

Note that the last one does not raise an error. What is the difference between calling assert with or without parenthesis that causes this behavior? My practice is to use parenthesis, but the above suggests that I should not.


回答 0

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

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

The last assert would have given you a warning (SyntaxWarning: assertion is always true, perhaps remove parentheses?) if you ran it through a full interpreter, not through IDLE. Because assert is a keyword and not a function, you are actually passing in a tuple as the first argument and leaving off the second argument.

Recall that non-empty tuples evaluate to True, and since the assertion message is optional, you’ve essentially called assert True when you wrote assert(1==2, "hi").


回答 1

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

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中也将完全删除。

If you put the parenthesis in there because you wanted a multi-line assert, then an alternative is to put a backslash at the end of the line like this:

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

Prints:

AssertionError: "derp should be 8, it is 7

Why does this python assert have to be different from everything else:

I think the pythonic ideology is that a program should self-correct without having to worry about the special flag to turn on asserts. The temptation to turn off asserts is too great, and thus it’s being deprecated.

I share your annoyance that the python assert has unique syntax relative to all other python programming constructs, and this syntax has yet again changed from python2 to python3 and again changed from python 3.4 to 3.6. Making assert statements not backward compatible from any version to any other version.

It’s a tap on the shoulder that assert is a 3rd class citizen, it will be totally removed in python4, and certainly again in Python 8.1.


回答 2

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

assert 1==2, "hi" is parsed as assert 1==2, "hi" with “hi” as the second parameter for the keyword. Hence why it properly gives an error.

assert(1==2) is parsed as assert (1==2) which is identical to assert 1==2, because parens around a single item don’t create a tuple unless there’s a trailing comma e.g. (1==2,).

assert(1==2, "hi") is parsed as assert (1==2, "hi"), which doesn’t give an error because a non-empty tuple (False, "hi") isn’t a false value, and there is no second parameter supplied to the keyword.

You shouldn’t use parentheses because assert is not a function in Python – it’s a keyword.


回答 3

您可以不\这样来破坏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'
)

You can break assert statement without \ like this:

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

Or if you have even longer message:

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

以下是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

Following is cited from the python doc

Assert statements are a convenient way to insert debugging assertions into a program:

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

The simple form, assert expression, is equivalent to if __debug__: if not expression: raise AssertionError

The extended form, assert expression1, expression2, is equivalent to if __debug__: if not expression1: raise AssertionError(expression2)

So when you’re using parenthesis here, you’re using the simple form, and the expression is evaluated as a tuple, which is always True when being casted to bool