我刚刚发现了这个:
a = (None,)
print (a is True)
print (a is False)
print (a == True)
print (a == False)
print (a == None)
print (a is None)
if a : print "hello"
if not a : print "goodbye"
产生:
False
False
False
False
False
False
hello
所以既不是,也不等于True或False,但在if语句中作为True。
为什么?
更新:
实际上,我刚刚意识到这并不像我想象的那么模糊。我得到a = 2的相同结果(虽然不是a = 0或a = 1,它们分别被认为等于False和True)答案 0 :(得分:13)
我发现这里几乎所有的解释都没有用,所以这是另一个尝试:
这里的混淆是基于“is”,“==”和“if”三种不同的测试。
这里有重要的部分:
现在也许这只是在我的头脑中更清楚,但至少我试过了。 :)
答案 1 :(得分:9)
a
是一个单成员元组,其结果为True
。 is
测试对象的身份,因此,您在所有测试中获得False
。 ==
测试对象的相等性,因此,您再次获得False
。
在if
语句中__bool__
(或__nonzero__
)用于评估对象,对于非空元组,它应返回True
,因此得到{{} 1}}。希望能回答你的问题。
修改:True
和True
分别等于False
和1
的原因是因为0
类型实现为bool
类型的子类。
答案 2 :(得分:2)
python中的内容不一定是True
或False
中的一个。
当它们用作if
/ while
循环的文本表达式时,它们会转换为布尔值。您无法使用is
或==
来测试他们评估的内容。您使用bool( thing )
>>> a = (None,)
>>> bool(a)
True
另请注意:
>>> 10 == True
False
>>> 10 is True
False
>>> bool(10)
True
答案 3 :(得分:2)
TL; DR:
if
和==
是完全不同的操作。 if
检查变量的真值,而==
比较两个变量。 is
也比较两个变量,但如果两个变量都引用相同的对象,则进行比较。
因此,将变量与True
,False
或None
进行比较以检查其真值是没有意义的。
if
时会发生什么?在Python中,if
之类的检查会隐式获取参数的bool
。所以
if something:
将(在引擎盖下)执行如下:
if bool(something):
请注意,您不应该在代码中使用后者,因为它被认为不那么pythonic而且速度较慢(因为Python然后使用两个bool
s:bool(bool(something))
)。 始终使用if something
。
如果您对CPython 3.6的评估方式感兴趣:
请注意,CPython并未在此处使用hasattr
。它会检查type
的{{1}}是否实现了该方法,但没有通过x
方法(__getattribute__
会使用该方法)。
在Python2中,该方法称为hasattr
而不是__nonzero__
__bool__
? ==
将检查是否相等(通常也称为“值相等”)。但是,此等式检查不会强制操作数(与其他编程语言不同)。 Python中的值相等是明确实现的。所以你可以这样做:
==
但是,如果任一操作数未实现比较,则>>> 1 == True # because bool subclasses int, True is equal to 1 (and False to 0)
True
>>> 1.0 == True # because float implements __eq__ with int
True
>>> 1+1j == True # because complex implements __eq__ with int
True
将默认引用比较(==
)。这就是原因:
is
因为>>> (None, ) == True
False
不支持与tuple
的平等,反之亦然。请注意,即使将列表与元组进行比较也是“不受支持的”:
int
如果您感兴趣,这就是CPython(3.6)实现相等的方式(橙色箭头表示操作是否返回>>> [None] == (None, )
False
常量):
这只是粗略正确,因为CPython还检查NotImplemented
或type()
的{{1}}是否实现value1
(不经过value2
方法!)它被调用(如果存在)或被跳过(如果它不存在)。
请注意,Python2中的行为明显更长(至少如果方法返回__eq__
)并且Python 2也支持__getattribute__
,
NotImplemented
? __cmp__
通常称为引用相等比较运算符。如果两个变量都引用完全相同的对象,它只返回is
。通常,保持相同值的变量可以引用不同的对象:
is
请注意,CPython使用缓存值,因此有时“应该”为不同实例的变量实际上是同一个实例。这就是为什么我没有使用True
(同一行中具有相同值的文字总是相等)以及为什么我不能使用>>> 1 is 1. # same value, different types
False
>>> a = 500
>>> a is 500 # same value, same type, different instances
False
作为示例(因为CPython重新使用值-5)到256)。
但回到你的比较:500 is 500
比较引用,这意味着如果两个操作数具有相同的类型和值但它们必须是相同的引用是不够的。鉴于它们甚至没有相同的类型(您将1
与is
和tuple
对象进行比较),bool
无法返回NoneType
请注意,is
,True
和True
(以及False
和None
)是CPython中的常量和单例。在这些情况下,这不仅仅是一种优化。
答案 4 :(得分:1)
(None,)是一个包含元素的元组,它不是空的,因此在该上下文中不会计算为False。
答案 5 :(得分:1)
因为a=(None,)
是包含单个元素None
使用a=None
再试一次,您会看到有不同的结果。
同时尝试a=()
这是空元组。其真值为false
答案 6 :(得分:0)
在Python中,可以使用bool
函数或__nonzero__
method将所有类型转换为bool()
。
示例:
False
。False
。__nonzero__()
。[编辑]
在您的代码中,使用(None,)
语句中的bool()
转换元组if
。由于它是非空的,因此评估为True
。