为什么在 Python 3 中 ... == True return 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('...')
    ...:     
...

根据 the documentation... 的真值为真。

但是我还是觉得上面的代码有点不一致

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

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 中,大多数(所有?)对象都有一个 bool 值。 "has a truth value of True" 背后的含义意味着 bool(obj) 的计算结果为 True。

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

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

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

文档中有更明确的explanation

Boolean values are the two constant objects False and True. They are used to represent truth values (although other values can also be considered false or true). In numeric contexts (for example when used as the argument to an arithmetic operator), they behave like the integers 0 and 1, respectively

来自文档中的 type-hierarchy 本身:

These represent the truth values False and True. The two objects representing the values False and True are the only Boolean objects. The Boolean type is a subtype of the integer type, and Boolean values behave like the values 0 and 1, respectively, in almost all contexts, the exception being that when converted to a string, the strings "False" or "True" are returned, respectively.

任何对象都可以测试 "truthiness":

Any object can be tested for truth value, for use in an if or while condition or as operand of the Boolean operations below. The following values are considered false:

  • None

  • False

  • zero of any numeric type, for example, 0, 0.0, 0j.

  • any empty sequence, for example, '', (), [].

  • any empty mapping, for example, {}.

  • instances of user-defined classes, if the class defines a bool() or len() method, when that method returns the integer zero or bool value False. [1]

All other values are considered true — so objects of many types are always true.

Operations and built-in functions that have a Boolean result always return 0 or False for false and 1 or True for true, unless otherwise stated. (Important exception: the Boolean operations or and and always return one of their operands.)

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

if 将在条件下隐式调用 bool,因此:

if ...:
    # something

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

if bool(...):
    # something

和:

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

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

我认为 1 == True 这很奇怪,而不是 ... != True

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

>>> issubclass(bool, int)
True

您混淆了两个概念:相等性检验和真值检验。它们在 Python.

中不相同

我认为触发这个问题的是 Python 当你做 if something 时隐式转换(它把东西转换成 bool) 但是当你做 something1 == something2.

时它 不会 做隐式转换

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

Truth-value testing

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

对于整数 __bool__ method returns True 除非整数值为 0(那么它是 False)。

省略号对象(... is the Ellipsis object) on the other hand doesn't implement __bool__ or __len__ 所以它总是 True

Equality testing

相等性测试依赖于两个参数的__eq__方法。它更像是一个操作链:

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

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

对于内置 Python 类型,这些操作是明确实现的。例如 integers implement __eq__ but the CHECK_BINOP 确保它 returns NotImplemented 如果另一个不是 integer.

Ellipsis 对象完全 doesn't implement __eq__

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

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

>>> 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].