False == 0 和 True == 1 是实现细节,还是由语言保证?

Is False == 0 and True == 1 an implementation detail or is it guaranteed by the language?

提问人:Eric O. Lebigot 提问时间:5/4/2010 最后编辑:mkrieger1Eric O. Lebigot 更新时间:10/13/2023 访问量:330675

问:

在 Python 中是否保证 和 ,(假设它们不是由用户重新分配的)?例如,是否以任何方式保证以下代码将始终产生相同的结果,无论 Python 版本如何(包括现有的和可能的未来版本)?False == 0True == 1

0 == False  # True
1 == True   # True
['zero', 'one'][False]  # is 'zero'

任何对官方文档的引用将不胜感激!

正如在许多答案中指出的,继承自 .因此,这个问题可以改写为:“文档是否正式说程序员可以依赖从整数继承的布尔值,其值为 01?这个问题与编写不会因为实现细节而失败的健壮代码有关!boolint

python 布尔 相等 语言-规范

评论

70赞 Eric O. Lebigot 5/5/2010
@S.Lott:提出上述问题的原因有很多。因此,在某些情况下,依赖整数布尔值会使您的代码更简单:您是否必须更改它?或者,你可能会发现其他人编写的代码中依赖于布尔值是整数的地方:你是否为了“修复”现有代码而中断了你在代码中修改的内容,或者你能放心当前的编码是合理的吗?还有很多其他的例子。更一般地说,了解游戏规则是件好事,这样你就可以玩得好,并以合理的方式编程。
10赞 Eric O. Lebigot 5/5/2010
@S.Lott:原来的帖子恰好回应了你的观点:问题本质上是“这是一个实现细节吗?”,因为我完全同意你的观点,即人们不应该依赖实现细节。如果布尔值是已知值的正式整数,那么问题中的代码不依赖于实现细节,这很好。
5赞 dan04 7/5/2010
@S. Lot:知道 False==0 和 True==1 可以更容易地计算序列中有多少个布尔值是真的:你可以只写 .否则,你必须写.sum(bool_list)sum(1 for x bool_list if x)
9赞 Eric O. Lebigot 7/6/2010
@dan:这是计算布尔值的一种方式。我会说这更明确;它的速度也快了大约 3 倍...... :)bool_list.count(True)
3赞 Eric O. Lebigot 8/20/2015
@akonsu 如答案所示,Python 布尔值实际上是整数的(特定子类)。此外,Python 显然类型;也许你的意思是它“不是静态类型的”?另外,我不确定你说的“我不会在代码中犯错误”是什么意思。现在,我不喜欢将布尔值与整数混合在一起,因为它们在概念上是不同的,我不介意 Python 布尔值不是整数,但知道它们是,值为 0 和 1,很有用。

答:

85赞 Erik Cederstrand 5/4/2010 #1

以下是讨论 Python 2.3 中新 bool 类型的 PEP:http://www.python.org/dev/peps/pep-0285/

将布尔值转换为 int 时,整数值始终为 0 或 1,但在将 int 转换为布尔值时,除 0 之外的所有整数的布尔值均为 True。

>>> int(False)
0
>>> int(True)
1
>>> bool(5)
True
>>> bool(-5)
True
>>> bool(0)
False

评论

0赞 Techniquab 2/9/2022
由于您提供了 bool 转换的示例,我想指出我刚刚遇到的一些导致我的代码 bool('0') 为 True 的错误
234赞 Olivier Verdier 5/4/2010 #2

在 Python 2.x 中,这不能保证,因为它可以重新分配。但是,即使发生这种情况,布尔值 True 和布尔值 False 仍会正确返回以进行比较。TrueFalse

在 Python 3.x 中,和是关键字,并且将始终等于 和 。TrueFalse10

在 Python 2 中的正常情况下,以及在 Python 3 中:

Falseobject 的类型是 :boolint

    object
       |
     int
       |
     bool

这是在您的示例中确实有效的唯一原因。它不适用于不是整数子类的对象,因为列表索引仅适用于整数或定义__index__方法的对象(感谢 mark-dickinson)。['zero', 'one'][False]

编辑:

当前的 python 版本和 Python 3 版本都是如此。python 2 的文档Python 3 的文档都说:

有两种类型的整数:[...]整数 (int) [...]布尔值 (bool)

在布尔小节中:

布尔值:这些表示真值 False 和 True [...]在几乎所有上下文中,布尔值的行为分别类似于值 0 和 1,例外情况是,当转换为字符串时,将分别返回字符串“False”或“True”。

对于 Python 2,还有:

在数值上下文中(例如,当用作算术运算符的参数时),它们 [False 和 True] 的行为分别类似于整数 0 和 1。

因此,布尔值在 Python 2 和 3 中被显式视为整数。

因此,在 Python 4 出现之前,您是安全的。;-)

评论

3赞 luc 5/4/2010
0 == 0.0 返回 True,而 ['zero', 'one'][0.0] 失败。['零', '一'][False] 之所以有效,是因为 bool 是 int 的子类。 (int.__subclasses__() 返回 [<type 'bool'>])
25赞 Mark Dickinson 5/4/2010
吹毛求疵:任何提供方法的对象都可以用作列表索引;不仅仅是 或 的子类。__index__intlong
0赞 Mark Dickinson 5/10/2010
啊,是的,它也在那里。但最好不要链接到 Python 3.0 文档:3.0 已死。:)
5赞 ToolmakerSteve 1/21/2014
回复:“在 Python 2.x 中,这不能保证,因为 True 和 False 可以重新分配”。恕我直言,虽然这是真的,但任何重新分配 True 或 False 的人都应该得到任何奇怪的后果。具体来说,在重新分配之前存储 True,然后在重新分配后将结果与 True 进行比较会中断。 => False。除了这种重新分配之外,默认值被标准化为 0 和 1,我相信依赖它是常见的做法;例如,索引到一个双元素数组中,其中 [0] 包含 false 大小写,[1] 为 true。a = True; True = 'i am an idiot'; a == True
0赞 Eric O. Lebigot 4/16/2019
我刚刚注意到另一个官方确认的事实,即 True 在实践中可以被认为是 1 和 False 0:docs.python.org/2/library/stdtypes.html#boolean-values。我把它添加到这个答案中。
23赞 Daniel G 5/4/2010 #3

在 Python 2.x 中,根本无法保证:

>>> False = 5
>>> 0 == False
False

所以它可能会改变。在 Python 3.x 中,True、False 和 None 是保留字,因此上述代码不起作用。

一般来说,对于布尔值,您应该假设 False 的整数值始终为 0(只要您不更改它,如上所述),但 True 可以具有任何其他值。我不一定会依赖任何保证,但在 Python 3.x 上,无论如何都会如此。True==1

评论

3赞 ToolmakerSteve 1/21/2014
Re “ True 可以有任何其他值。我不一定会依赖任何保证 True==1”。实际上,您可以依赖 True==1,根据 python.org/dev/peps/pep-0285 和规范 docs.python.org/2/reference/...“布尔值在几乎所有上下文中的行为分别类似于值 0 和 1......”我并不是说不可能在 Py 2 中通过重新分配 True 或 False 来覆盖这一点,但我是说,除非你项目中的某个程序员是白痴并且进行这样的重新分配,否则这种行为是有保证的。
0赞 SL5net 1/13/2021
顺便说一句,切换太 python 风格有时会出现问题。检查: ''' if not (2 != 2): # <== that's ok print (“Hello, world!”) if !(1 != 2): # <== 语法Error print (“Hello, world!”) ''' rextester.com/VSTV98648
0赞 Max 6/30/2021
当它说是 时,这实际上意味着它是吗?0==FalseFalse5
0赞 chepner 9/11/2021
这会将名称与绑定到内置作用域中名称的类型值混淆。Boolean 值始终等于 0,无论可能为名称分配什么值。Falsebool
2赞 Dhaval Gojiya 6/29/2023 #4

让我们把这个问题分成两部分。

蟒:

print(45 == "45")  # Output - False

Javascript的:

console.log(45 == "45")  # Output - true

在这里,大多数人认为 Javascript 只检查双方对象的值,但事实并非如此,编写类似于 。
但是现在你有一个问题,如果两种语法相似,为什么我会得到不同的结果?
console.log(45 == "45")print(45 == "45")

在:Javascript

  • 运算符在比较值之前执行类型强制。这意味着 JavaScript 将尝试在评估相等性之前将操作数转换为通用类型。==
  • 在 JavaScript 中,字符串会自动转换为数字,因为另一个操作数是一个数字。JavaScript 尝试执行隐式类型转换来进行比较。字符串可以转换为数字,因此比较的计算结果为 。45 == "45""45""45"4545 == "45"true
  • 与 Python 关键字类似,Javascript 有一个比较运算符。检查两个侧对象是否位于同一计算机RAM内存位置。is===

在:Python

  • 在 Python 中,有不同的类型。 是 的实例,并且是 的实例。它们不是同一类的实例。45"45"45class <integer>"45"class <string>
  • 与 Javascript 不同,Python 不做内部类型转换,所以计算 .print(45 == "45")False
  • Python 使用内部类型转换,是的,你没听错,但这里有一个条件。Python 将仅对类型对象使用内部类型转换。boolean
  • 因此,在表达式中,布尔值 True 在执行比较之前被隐式强制转换为整数。结果,对比较进行评估,即 。print(True == 1)1print(1 == 1)True
  • 当你写的时候,相当于 .当 Python 解释器在执行此代码之前到达此行代码时,它会转换为 ,所以最后它变成 现在根据规则,两个侧对象和 are 相同,因此您会在终端中看到输出。print(True == 1)print(1 == 1)print(True == 1)print(int(True) == 1)print(1 == 1)==valuetype <class int>True
  • 同样,等价于 并最终计算为 。print(False == 0)print(int(False) == 0)print(0 == 0)True

点击这里查看。

# Normal behavior
sample_1 = True
print(sample_1) # Output - True
print(int(sample_1)) # Output - 1

sample_2 = False
print(sample_2) # Output - False
print(int(sample_2)) # Output - 0


# Try with True - boolean
A = True + 5  # equivalent to `A = int(True) + 5`
print(A) # Output - 6 (True ---> 1)


# Try with False - boolean
B = False + 5 # equivalent to `A = int(False) + 5`
print(B) # Output - 5 (False ---> 0)


# Try both boolean together
final = False + True # equivalent to `final = int(False) + int(True)`
print(final) # Output - 1  (False ---> 0 & True ---> 1)

希望对大家有所帮助!