为什么…==Python 3中的True返回False?

为什么…==Python 3中的True返回False?,python,python-3.x,if-statement,truthiness,Python,Python 3.x,If Statement,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 (...):

我正在学习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('...')
    ...:     
...
在python中,大多数(所有?)对象都有
bool
值。“真值为真”的含义意味着
bool(obj)
的计算结果为真

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

sum([True, True, False])
# (1 + 1 + 0) -> 2
这就是为什么会得到
1==True
-->
True

文档中有一个更明确的定义:

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

从文档中的自身:

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


任何物体都可以进行以下测试:


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

  • 没有

  • 假的

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

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

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

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

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

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

因此不难看出,
如果…
将进入分支。
省略号
对象被视为
true
。然而,这并不意味着它必须等于
True
。只有
bool(…)==True

if
将根据条件隐式调用
bool
,因此:

if ...:
    # something
将被评估为您编写了:

if bool(...):
    # something
以及:


然而,这里有一个陷阱
True
等于
1
False
等于
0
,但那只是因为python中的
bool
子类
int
eger。

我相信这是
1==True
这很奇怪,不是
…=正确

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

>>> issubclass(bool, int)
True

你混合了两个概念:平等性测试和真值测试。它们在Python中是不同的

我认为引发这个问题的原因是Python在你做
某件事的时候做了一个隐式转换(它把某件事转换成
bool
),但是当你做
something1==something2
的时候它不做隐式转换

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

  • 它首先检查对象是否实现了
    \uu bool\uu
    方法,如果实现了,则使用返回的布尔值
  • 如果它没有定义
    \uuuu bool\uuuu
    方法,它将查看
    \uuu len\uuu
    方法。如果它被实现,它将使用
    len(obj)!=0
  • 如果没有任何一个,则该对象被视为
    True
对于整数,返回
True
,除非整数值为
0
(然后为
False

另一方面,省略号对象()总是
True

相等性测试依赖于两个参数的
\uuuuuu eq\uuu
方法。这更像是一个操作链:

  • 当第二个操作数作为参数传递时,它检查第一个操作数是否实现了
    \uuuuuu eq\uuuu
  • 如果没有,则当第一个操作数作为参数传递时,它会检查第二个操作数是否实现了
    \uuuuu eq\uuuu
  • 如果没有,Python将检查对象标识(如果它们是相同的对象-类似于类C语言中的指针比较)
这些操作的顺序可能会有所不同。1

对于内置Python类型,这些操作是显式实现的。例如,但如果另一个不是
int
eger,则确保返回
NotImplemented

省略号根本就是对象

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

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

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

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

尽管源代码可能很难理解,但我希望我已经充分解释了这些概念(源代码是针对CPython实现的,其他pypypy、IronPython等Python实现中的实现可能有所不同!)。重要的附加信息应该是Python在平等性检查中不进行隐式转换,平等性测试与tr无关
>>> issubclass(bool, int)
True
>>> 1 == True
True
>>> 0 == False
True

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