为什么 `True == False is False` 的结果是False?

110

我在使用==时得到了一些意外的结果,但是在使用is时却无法正常工作:

>>> (True == False) is False
True
>>> True == (False is False)
True
>>> True == False is False
False
>>> id(True)
8978640
>>> id(False)
8978192
>>> id(True == False)
8978192
>>> id(False is False)
8978640

1
哦,事实证明这与is==无关,因为在任何情况下该表达式的值都为False。感谢各位的快速回答! - raylu
@MartijnPieters 在我回答的时候,我想这个问题以前一定被问过了,但是我猜可能很难通过谷歌找到。这个问题可能是另一个重复的问题。 - jorgeca
与我的问题相关:[为什么(1 in 1,0] == True)的结果是False? - Peter Wood
2
我认为这会是一个非常好的面试问题,适合问那些在被问到“在1-10的等级中,你的 Python 技能如何?”时回答“10”的人。 - Bryan Oakley
为什么这个表达式应该是True?完全没有理由:True is False的结果是False,True == False也是False,那么为什么True == False is False的结果却应该是True呢? - jpic
1
@jpic:我认为问题的本质在于,许多人会写 True == False is False,以为它会被解析为 (True == False) is False,从而计算出 FALSE is False,因此应该为 True。 - roberto
4个回答

188

实际上这是一个链式比较,因此

True == False is False

等价于

(True == False) and (False is False)

在这种情况下可能会令人惊讶,但是您可以编写 1 <= x < 4 这样的代码,这与其他语言(如C)不同。


1
(顺便说一下,括号并不总是必要的)将以下与编程有关的内容从英语翻译成中文。仅返回已翻译的文本: - jorgeca
1
显然,这仅适用于它们具有相同的优先级。 - NullUserException
@NullUserException 嗯,我认为它们不需要,因为可能的运算符是"<" | ">" | "==" | ">=" | "<=" | "<>" | "!=" | "is" ["not"] | ["not"] "in",它们的优先级都比and低。(顺便说一句,感谢您对语法的修正,这真的帮助了我们非母语人士)。 - jorgeca
38
这就是为什么我倾向于用括号来包含复合逻辑比较,因为我无法记住我使用的所有语言中的语法,而且不值得冒略掉它们并产生意外行为的风险。 - zzzzBov
7
我完全同意,这就是为什么我已经将它们包装起来了 ;) - jorgeca
显示剩余2条评论

37

文档中得知:

x < y <= z 等价于 x < y and y <= z,但是当 x < y 为假时,在两种情况下都不会评估 z,只评估一次 y。

在您的情况下,True == False is False等价于True == False and False is False,因为第一个条件为False,所以它短路并返回False

>>> dis.dis(lambda : True == False is False)
  1           0 LOAD_GLOBAL              0 (True)
              3 LOAD_GLOBAL              1 (False)
              6 DUP_TOP             
              7 ROT_THREE           
              8 COMPARE_OP               2 (==)
             11 JUMP_IF_FALSE_OR_POP    21          <---------this step
             14 LOAD_GLOBAL              1 (False)
             17 COMPARE_OP               8 (is)
             20 RETURN_VALUE        
        >>   21 ROT_TWO             
             22 POP_TOP             
             23 RETURN_VALUE  

9
谢谢您使用 dis.dis(),我学到了有用的东西。 :) - pymd
2
我没有点踩,但在我看来,语言规则的描述已经足够理解正在发生的事情了。反汇编似乎并没有增加太多内容(除了关注于实现特定的细节)。 - cHao

9

来自文档

5.9. 比较

与C语言不同,在Python中所有比较操作的优先级相同,低于任何算术、移位或按位操作。而且与C语言不同的是,类似于 a < b < c 的表达式在数学上的解释是惯例:

comparison    ::=  or_expr ( comp_operator or_expr )*
comp_operator ::=  "<" | ">" | "==" | ">=" | "<=" | "<>" | "!="
                   | "is" ["not"] | ["not"] "in"

4
True == False is False 是一种链式比较,意思与 (True == False) and (False is False) 相同。由于第一个比较 (True==False) 是 false,所以链式比较的结果是 False。

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