为什么'True == not False'会出现语法错误?

49

在Python中,使用==可以比较布尔值。但是当我应用布尔运算符not时,结果会出现语法错误:

Python 2.7 (r27:82500, Sep 16 2010, 18:02:00) 
[GCC 4.5.1 20100907 (Red Hat 4.5.1-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> True == True
True
>>> False == False
True
>>> True is not False
True
>>> True == not False
  File "<stdin>", line 1
    True == not False
              ^
SyntaxError: invalid syntax
>>> 
为什么这是语法错误?我期望 not False 是一个返回布尔值的表达式,而且无论在哪里使用 <x> 都应该是有效的语法。

13
请注意,“True不是False”与“True is(not False)”并不相同。“is not”是一个独立的运算符,它的意思是“不完全等于”,而“True is(not False)”则表示“True等于False的布尔取反”。这只是一种提示,因为您的例子似乎假定这两者是相同的。 - user355252
1
"True == not" 是实际的语法错误,其后的任何内容都是无关紧要的。 - dansalmo
5
记录一下,这个问题会对 任何 比较运算符加上 not 失败, 不论所比较的类型如何。例如:True < not False3 <= not 2'Foo' > not 'False'3.3 >= not 4.5{} is not not []set() == not Noneslice() != not lambda: x 会引发相同的语法错误。 这并不仅限于 == not 和布尔值。 - Martijn Pieters
5个回答

56

这与Python中的运算符优先级有关(解释器认为您正在将True与not进行比较,因为 == 的优先级高于 not )。 您需要添加一些括号以明确操作顺序:

True == (not False)

通常情况下,你不能在比较操作符的右侧使用not而不加括号。然而,我想不出有什么情况需要在比较操作符的右侧使用not


1
运算符优先级是否有其存在的理由,还是只是一个愚蠢的“特性”? - Jim Clay
@Jim 运算符优先级对于一种语言理解操作发生的顺序是必要的。算术运算符是基于数学的(不知道你是否听说过PEMDAS),但布尔/比较运算符则有些棘手。不同的语言有不同的解释,但在Python中是这样的。如果您大量使用括号,通常不会出现问题。我不知道Python有任何特定的原因。 - Rafe Kettler
7
Python 中逻辑反转的优先级较低。相比之下,算术取负(一元 -)和位反转 (~) 的优先级都很高。 - ncoghlan
2
当然,就像 Python 中的几乎所有东西一样,这是很有道理的,因为 == not 看起来很奇怪,在大多数情况下都可以用 != 替代。 - Lennart Regebro
2
@JimClay 原因可能是为了与其他比较运算符保持一致,这种优先级在我看来非常合理:在 if not (foo.x * 2) + 1 < bar 中,你不会期望 not (foo.x*2) + 1 意味着 "如果 (foo.x*2) + 1 == 0 则为 1,否则为 0",然后再将其与 bar 进行 "小于" 比较。在某些情况下,否定涉及 "<" 的语句比否定 "<" 本身转换为 ">=" 更易读。 - Nearoo
显示剩余4条评论

8
声称True == not False导致语法错误的答案与运算符优先级无关。如果是这种情况,表达式2 ** - 1也将产生语法错误,但它显然没有这样做。优先级从未导致运算符代替操作数。
造成True == not False成为语法错误的真正原因是不存在任何语法规则会产生比较,因为

comparison ::= or_expr (comp_operator or_expr)*

即在comp_operator==之后必须跟随一个or_expr,其中包括一个xor_expr、一个and_expr、一个shift_expr、一个a_expr、一个m_expr、一个u_expr、一个power……,但没有not_test
相比之下,根据幂运算规则,优先级类似的结构2 ** - 1

power ::= (await_expr | primary) ["**" u_expr]

在幂运算符**之后有u_expr,因此允许右侧有- x

1
可能值得一提的是,在这里not适用的地方:inversion要么是由'not'后跟另一个inversion所组成,要么是由comparison所组成。inversion是一个conjunction的基本组成部分,而conjunction又是disjunction的基本组成部分,你可以将其基本上视为expression三种基本类型之一(另外两种为条件表达式和lambda表达式)的其中之一。 - chepner
2
这个参数是无效的。当然,优先级可以解释True == not False2 ** -1的行为,因为*not和一元否定有完全不同的优先级!* or_expr不包括not_test这个事实就是优先级如何实现的! - Karl Knechtel
1
"not和一元取反操作完全具有不同的优先级"这个论点是无关紧要的; 相关的是==not**-之间的优先级差异。将优先级与解析混合在一起的坚持使得Python文档自相矛盾,首先在运算符优先级表中将**置于-之上,然后指出_[5]乘幂操作符**的绑定比算术或位运算一元操作符更弱..._。 - Armali
1
在运算符优先级表中,== 恰好位于 not 的上方一行,而 ** 恰好位于一元负号 - 的上方一行。如何才能相信仅凭优先级就能解释为什么 True == not False 是语法错误而 2**-1 不是呢? - undefined
**和一元-并不真正遵循一个清晰的优先级层次结构。它们被放在优先级表中是因为以其他方式处理会更加尴尬,但是说一个比另一个的优先级更高并不准确地描述了这些运算符的语法工作方式(因此有脚注)。打破优先级层次结构是值得的,因为**是常见的操作,x**-1是一个常见的操作,并且**是非交换的,所以当x**-1-x**2被解析为不同的结果时,人们不会感到太惊讶...但是人们仍然会对-2**x被解析为-(2**x)感到惊讶。 - undefined

6

这只是操作优先级的问题。请尝试:

>>> True == (not False)
True

请看运算符优先级表,你会发现==not的优先级更高,因此True == not False被解析为(True == not) False,这明显是一个错误。


-3

我认为你要找的是 "and not"。这将给你想要的结果。如果你正在比较布尔值,那么你所拥有的是一个复合布尔表达式,这里有一个示例网站 Compound Boolean Expression

>>> True and True
True
>>> True and not True
False
>>> True and not False
True
>>> False and not True
False
>>> False and not False
False
>>> False and False
False

-3
Python有运算符优先级(这类似于数学中的Bodmas。某些运算符比其他运算符更优先。例如:乘法运算符在加法之前被考虑)。在Python中,“==”在运算符优先级中排在“not”之前。因此,在您的代码行中,Python分析的第一件事是“False == not”。由于这是不正确的语法,因此会引发错误。

这并没有为已经存在了十多年的答案增加任何内容。 - roganjosh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接