为什么在Python中1 == True但2!= True?

34

可能是重复问题:
在Python中,False == 0和True == 1是语言保证还是实现细节?


我的交互式控制台中的简要记录:

Python 2.7.2 (default, Jun 29 2011, 11:10:00) 
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> True
True
>>> 0 == True
False
>>> 1 == True
True
>>> 2 == True
False

为什么会出现这种情况?

编辑:为了对比,请考虑is运算符。

>>> 0 is False
False
>>> 1 is True
False
>>> 0 is 0
True
>>> True is True
True

这很有道理,因为尽管1Trueif语句的条件中具有相同的含义,但它们并不是完全相同的东西。

再次编辑:1 == True还有更多有趣的结果:

>>> d = {}
>>> d[True] = "hello"
>>> d[1]
"hello"

4
请参见"true"的定义:http://docs.python.org/reference/expressions.html#booleans - Fredrik Pihl
31
问题应该是为什么 2 != True - Mchl
docs.python.org 上有一份参考手册吗? - mjv
3
在Visual Basic中,True的标识为True=-1,False的标识为False=0。如果你在VB中测试True=+2True=1False=0.4575False=-999,它们都会返回false。在Python中:同样的思路,具体细节不同。2 != True并不神秘。 - Jean-François Corbett
嗯,关于 d[1] is d[True] 的部分是出乎意料的... - Armando Pérez Marqués
显示剩余2条评论
8个回答

37

因为在Python中,布尔值是整数的一个子类型。根据文档:

布尔值是两个常量对象False和True。它们用于表示真值(尽管其他值也可以被认为是假或真)。在数字上下文中(例如当作算术运算符的参数时),它们分别像整数0和1一样运行。如果可以将值解释为真值,则可以使用内置函数bool()将任何值强制转换为布尔值(请参见上面的“真值测试”一节)。

http://docs.python.org/library/stdtypes.html#boolean-values


1
是的,这解释了“如何”,但这似乎是一个奇怪的决定。这意味着==有非常奇怪的行为。我更喜欢is运算符的行为方式,其中布尔值和整数永远不相等。 - Clueless
9
@Clueless:小心使用“is”关键字,因为在某些情况下,整数之间并不相等:Python中的“is”运算符对整数的行为与预期不同 - Greg Hewgill
2
@Clueless Python的设计者选择让一个类型的值看起来比其他类型的值更频繁地表现为另一种类型的值。Python不像Java那样,布尔值和整数不能隐式互换。尽管如此,当需要“分离”时,您可以使用Python内置的type函数。链接 - Ray Toal
@Ray Toal 当 bool 类型被实现时,确实有很多关于这个话题的讨论。我认为他们最终选择当前的实现方式是为了向后兼容(尽管我担心有一天我会发现一个程序在布尔值上使用整数运算)。 - Voo
@Voo 在进行代码高尔夫时偶尔会有帮助。("thing 1","thing 2")[x==0]。不过我不确定“对代码高尔夫有帮助”是任何语言特性的好事情。 - Clueless
显示剩余2条评论

28

在 Python 中,bool 类型的实例也是 int 类型的实例,True 恰好等于整数 1

看下面这个例子:

[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> isinstance(True, int)
True
>>> int(True)
1
>>> 

1
抱歉打扰了一个好答案,但是 <pedantic> 没有 boolean 类型 - 它是 bool,而且 isinstance(bool, int) == False,所以我认为你的意思是 "bool 的实例也是 int 的实例" 或者 "布尔值是 int 的实例"。</pedantic> 祝好。 - Ray Toal
@Ray Toal:感谢您指出这一点。非常有帮助。已经根据您刚才提到的内容更正了答案。 - Pablo Santa Cruz
1
好的,现在给你一个良好回答徽章的点赞。顺便说一下,isinstance 的使用很棒。能够很好地解释为什么 2 != True - Ray Toal

13

这是标准二进制约定:1表示true,0表示false。

就像在机器语言中,1表示“on”,0表示“off”一样。

因此,在Python中,bool类型只是int的一个子类型,其中1 == True0 == False

但是,在条件语句中,任何非零数字值都将被评估为True

>>> if 2: print "ok"
ok
>>> 2 == True
False

实际上,至少有一种编程语言将true定义为-1(事实上Win32也很少使用该定义)。听说这导致了一些非常有趣的bug。 - Voo
为了解释我的答案,原始问题并没有提到 2 != True,它只是“为什么在Python中 1 == True?”后来进行了编辑。 - machine yearning

12

很久以前(在Python < 2.3中),没有布尔类型,没有 FalseTrue,只有 01。然后,PEP 285 出现了,它们被添加到了语言中。它们被定义为 True == 1False == 0,可能是为了向后兼容的原因。


5

相等测试与布尔测试不同:

>>> bool(1)
True
>>> bool(2)
True
>>> bool(-1)
True
>>> bool(0)
False

对我来说,== 应该要么识别 Python 解释为“True”的所有值,要么就应该是严格的。它并不是松散的,因为 2 == True 计算结果为 false,它也不是严格的,因为 1 == True 计算结果为 true,尽管它们完全是不同的类型。所以它是不一致的。 - Clueless
3
但是如果你允许这样,你就可以“证明”1==2,因为你会期望相等操作具有传递性(因此1 == True == 2)。现在这也非常不一致,并且我认为更加有问题;) - Voo
1
这并不是非常遥远的概念。它只是一个非零整数的等价类而已。但我同意,我们不希望 1 == 2 在一般情况下成立,因为这会使运算符变得毫无用处。更好的做法是让 1 == True 为假,因为在数学上它们是完全不同的东西。 - Clueless

0

这是一个布尔值。1 == true,0 == false。


0

因为在二进制中,1代表真,0代表假。这也适用于PHP。

我不确定其他编程语言是否也是如此。


那么在Python中的"is"是否等同于PHP中的"==="? - koosa
1
@Mark:(免责声明:我对Python的了解不是很深)但从我在这里读到的内容来看,似乎“is”更像是一个引用检查,这就是为什么“2 is 2”可能会是假的原因。 - Matthew Scharley

-1

这是二进制的。0始终为False,1始终为True。但在Python中,任何非零值,包括负值,始终为True。

>>> if -1:
...     print 'a'
...
a
>>> if 2:
...     print 'a'
...
a
>>> if 0:
...     print 'a'
...
>>>

3
在Python中,任何非零值,包括负数值,始终为True。但是,他刚刚粘贴了一个演示这并非完全正确的代码片段。 - Gabi Purcaru
正如比尔·克林顿可能会说的那样,“are”的意思取决于什么。 2 is True是错误的(1 is True也是)。当然,bool()将为非零整数输入返回True,但这并不意味着这些值“是”True - Wooble
这段代码证明了2不是一个二进制数,但它并不能证明Python会将非零数字、列表等视为True。 - Ben
1
这个回答有点绕开了问题。OP想知道为什么1 == True但是2 != True。相等性不同于“在布尔上下文中进行评估”。 - Ray Toal

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