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

smw*_*dia 10 python if-statement python-3.x truthiness

我正在学习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('...')
    ...:     
...
Run Code Online (Sandbox Code Playgroud)

根据文档,...真值为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
Run Code Online (Sandbox Code Playgroud)

MSe*_*ert 9

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

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

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

真值测试

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

对于整数,该__bool__方法返回,True除非整数值是0(然后是False).

另一方面,省略号对象(...是省略号对象)没有实现__bool__,__len__所以它总是如此True.

平等测试

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

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

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

对于内置Python类型,这些操作是显式实现的.例如integers实现__eq__CHECK_BINOP确保NotImplemented如果另一个不是integer 则返回.

Ellipsis对象根本没有实现__eq__.

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

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

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

>>> 1 == False
False
>>> 0 == True
False
Run Code Online (Sandbox Code Playgroud)

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

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

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


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

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


MSe*_*ert 6

任何对象都可以测试"真实性":

可以测试任何对象的真值,用于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
Run Code Online (Sandbox Code Playgroud)

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

if bool(...):
    # something
Run Code Online (Sandbox Code Playgroud)

和:

>>> bool(...)
True
>>> bool(1)
True
>>> bool(2)
True
Run Code Online (Sandbox Code Playgroud)

但是这里有一个问题.True等于1False等于0,但这只是因为python中的bool子类integer.

  • @Chris_Rands它使用[`PyObject_IsTrue`](https://docs.python.org/3/c-api/object.html#c.PyObject_IsTrue)或[`PyObject_Not`](https://docs.python.组织/ 3/C-API/object.html#c.PyObject_Not).这些将调用`__bool__`(和`__len__`)方法或C等价物.`bool()`也使用相同的特殊方法_but_除了检查真值之外,它还会显式返回一个布尔对象.所以当你有`if bool(...)`你实际上调用`(...).__ bool __().__ bool __()`和`if ...`你调用`(...).__ bool __( )`.这不是100%正确,因为我们正在处理C函数和类型. (2认同)