繁体   English   中英

为什么... = = True在Python 3中返回False?

[英]Why does … == True return False in Python 3?

我正在学习python,但是我对以下结果感到有些困惑。

In [41]: 1 == True
Out[41]: True

In [42]: if(1):
    ...:     print('111')
    ...:     
111

In [43]: ... == True
Out[43]: False <===== why this is False while '1 == True' is True in previous sample

In [44]: if (...): <==== here ... just behaves like True
    ...:     print('...')
    ...:     
...

根据文档...的真值为True。

但我仍觉得上面的代码有点不一致。

......更有趣的事情:

In [48]: 2==True
Out[48]: False <===== why 1==True returns True while 2==True returns False?

In [49]: if(2):
    ...:     print('222')
    ...:     
222

你混合了两个概念:平等测试和真值测试。 它们在Python中不一样。

我认为触发这个问题的是,当你if something (它将if something内容转换为bool ),Python 进行隐式转换,但是当你执行something1 == something2时,它不会进行隐式转换。 something1 == something2

Pythons数据模型实际上解释了这些操作是如何完成的:

真值测试

  • 它首先检查对象是否实现了__bool__方法,如果是,则使用返回的布尔值。
  • 如果它没有定义__bool__方法,它会查看__len__方法。 如果它被实现,它将使用len(obj) != 0
  • 如果它没有任何对象被认为是True

对于整数, __bool__方法返回True除非整数值为0 (然后它为False )。

另一方面,省略号对象( ...是省略号对象没有实现__bool____len__因此它总是为True

平等测试

等式测试依赖于两个参数的__eq__方法。 它更像是一系列运营:

  • 当第二个操作数作为参数传递时,它检查第一个操作数是否实现__eq__
  • 如果没有,那么当第一个操作数作为参数传递时,它检查第二个操作数是否实现__eq__
  • 如果没有,则Python检查对象标识(如果它们是同一个对象 - 类似于C语言中的指针比较)

这些操作的顺序可能会有所不同。 1

对于内置Python类型,这些操作是显式实现的。 例如int egers实施__eq__CHECK_BINOP确保它返回NotImplemented如果对方一个不是int埃格尔。

Ellipsis对象根本不实现__eq__

因此,当您比较整数和省略号时,Python将始终回退到对象标识,因此它将始终返回False

另一方面, bool eans是int egers的子类,因此它们实际上与int进行比较(毕竟它们是另一个int )。 布尔值实现为1True )和0False )。 所以他们比较平等:

>>> 1 == True
True
>>> 0 == False
True

>>> 1 == False
False
>>> 0 == True
False

尽管源代码可能很难理解,但我希望我能够很好地解释这些概念(源代码用于CPython实现,其他Python实现中的实现,如PyPy,IronPython可能会有所不同!)。 重要的外卖消息应该是Python不在等式检查中进行隐式转换,而等式测试根本不与真值测试相关。 实现了内置类型,它们几乎总能给出可感知的结果:

  • 所有数字类型都以某种方式实现相等(浮点数与整数比较,复数比较整数和浮点数)
  • 并且所有不归零和不空的都是truthy

但是,如果您创建自己的类,您可以根据需要覆盖相等和真值测试(然后您可以传播很多混淆)!


1在某些情况下,订单会发生变化:

  1. 如果第二个操作数是第一个操作数的子类,则前两个步骤相反。
  2. 对于某些隐式等式检查,在调用任何__eq__方法之前检查对象标识。 例如,当检查某个项目是否在列表中时,即1 in [1,2,3]

任何对象都可以测试“真实性”

可以测试任何对象的真值,用于if或while条件或下面的布尔运算的操作数。 以下值被视为false:

  • 没有

  • 任何数字类型的零,例如,0,0.0,0j。

  • 任何空序列,例如'',(),[]。

  • 任何空映射,例如{}。

  • 用户定义类的实例,如果类定义bool ()或len ()方法,则该方法返回整数零或bool值False。 [1]

所有其他值都被认为是真的 - 因此许多类型的对象始终是真的。

除非另有说明,具有布尔结果的操作和内置函数总是返回0或False表示false,1或True表示true。 (重要的例外:布尔运算或者并且始终返回其中一个操作数。)

所以不难看出, if ...将进入分支机构。 Ellipsis对象被认为是true 然而,这并不意味着它必须等于True 只是bool(...) == True

if会在条件上隐式调用bool ,所以:

if ...:
    # something

将被评估,就好像你写了:

if bool(...):
    # something

和:

>>> bool(...)
True
>>> bool(1)
True
>>> bool(2)
True

但是这里有一个问题。 True等于1False等于0 ,但是这只是因为boolint在python埃格尔。

在python中,大多数(所有?)对象都有bool值。 “具有True的真值”背后的含义意味着bool(obj)计算结果为True。

另一方面,在许多情况下, True被视为1 (并且False0 ),当您执行以下操作时,您可以看到:

sum([True, True, False])
# (1 + 1 + 0) -> 2

这就是为什么你得到1 == True - > True

文档中有更明确的解释

布尔值是两个常量对象False和True。 它们用于表示真值(尽管其他值也可以被认为是假或真)。 在数值上下文中(例如,当用作算术运算符的参数时),它们的行为分别为整数0和1

从文档中的类型层次结构本身:

这些代表真值False和True。 表示值False和True的两个对象是唯一的布尔对象。 布尔类型是整数类型的子类型, 布尔值在几乎所有上下文中的行为分别类似于值0和1,例外的是,当转换为字符串时,返回字符串“False”或“True” , 分别。

我相信这是1 == True这里1 == True很奇怪,不是... != True

1等于True因为在Python中,布尔值是整数的子类(因为PEP-285 )。 看看自己:

>>> issubclass(bool, int)
True

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM