Python:比较空字符串和False的结果是False,为什么?

5
如果not ''的结果为True,为什么'' == False的结果会是False
例如,其他类型(如0、0.0)的“空值”在与False进行比较时,将返回True
>>> 0 == False
True
>>> 0.0 == False
True

谢谢


1
空序列计算结果为 False,但并不等于 False。请参考这里:https://dev59.com/Umkw5IYBdhLWcg3w6Opy#9573259(前两个答案都涉及到了这个问题)。 - Tomasz Plaskota
1
谢谢。尽管如此,我的问题仍然是:为什么? - Tony Power
@TonyPower 因为这就是选择实现Python的方式。对于问题“为什么”,没有真正的答案。此外,为什么一个空列表会等于False呢?它仍然是一个列表,只是空的而已。 - DeepSpace
5个回答

10
在布尔运算中,以及当表达式由控制流语句使用时,以下值被解释为 false:FalseNone、所有类型的数字零以及空字符串和容器(包括字符串、元组、列表、字典、集合和冻结集合)。所有其他值都被解释为 true。用户定义的对象可以通过提供一个 __bool__() 方法来自定义它们的真值。 如果其参数为 false,则运算符 not 产生 True,否则产生 False。 参考链接:https://docs.python.org/3/reference/expressions.html#comparisons 运算符 <, >, ==, >=, <=!= 比较两个对象的值。这些对象不需要具有相同的类型。
由于所有类型都是(直接或间接)object 的子类型,它们从 object 继承默认的比较行为。类型可以通过实现如 __lt__() 等丰富比较方法来自定义其比较行为。 https://docs.python.org/3/reference/expressions.html#boolean-operations 因此,技术实现的答案是这种行为方式是由于not==使用不同的比较方法。 not使用__bool__,即对象的“真值”,而==使用__eq__,即将一个对象直接与另一个对象进行比较。因此,可以询问对象它是否被认为是“真”的或“假”的,并且单独地询问它是否认为自己与另一个对象相等或不相等。默认实现的方式是两个对象都可以认为自己是假的,但彼此之间不认为相等。

6
< p>让< code>''和< code>[]等于< code>False没有意义,因为它们显然是不同的值:一个字符串和一个列表。如果它们都等于< code>False,那么它们必须相等*。它们只是"falsey",这意味着当它们转换为布尔值时,它们会变成false。

(*在任何合理构建的语言中)

< code>not是一个返回布尔值的操作。它返回的布尔值取决于操作数是否为falsey。因此,< code>not x不等同于< code>x==False;它等同于< code>bool(x)==False。


1
咳咳,看看 PHP 的逻辑:[] == false; '' == false; [] != ''; 是的... - deceze
因此,在我的注释处* - khelwood
所以,您是在说''不等于False是不明智的,但是将0视为False是有意义的?我知道布尔逻辑都是关于0和1的,但对我来说,将''视为False和将not ''视为True一样有意义。 - Tony Power
Python表达式'' is False的结果为false,因为is只有在操作数是指向同一对象的引用时才返回True。'' is True也以完全相同的原因评估为false。 - holdenweb
1
@TonyPower 在Python中,boolint的子类。但这并不适用于liststr。基本上,FalseTrue只是01的特殊实例。例如,True + 2 == 3,而[] + 2会出错。如果它们相等,则需要能够执行字符串、列表和整数的其他类型操作。 - Dunes

1
这样的比较不符合"Pythonic"(即,不是有经验的Python程序员自然会做的事情)。Pythonic的方法是在布尔上下文中使用值,例如if语句,并让解释器隐式地应用bool内置函数来确定TrueFalse的值。这就是为什么人们通常编写以下代码的原因。
if lst:
    print(headers)
    for item in lst:
        print(item.format())
else:
    print(no_data_message)

相比使用常见但不太Pythonic的if len(lst):或者更加笨拙但依然正确的if len(lst) > 0:,更好的方法是使用if not lst:

不幸的是,在某些方面上,Python的设计者决定TrueFalse将成为bool类型的实例,而bool将是int的子类。因此,True等于1,而False等于0。数值转换解释了浮点数(以及复数)的结果。

但只是因为bool(x) == True并不意味着x == True,就像bool(x) == False也不意味着x == False一样。还有许多其他的值会被视为假,其中最著名的是

  • 数字零
  • None
  • 空字符串
  • 空容器(列表、元组、字典)

它们之间没有办法都相等!


1
这很有道理。谢谢。 - Tony Power
1
这对我来说是最有价值的回答,因为它实际上解释了为什么__eq__运算符会表现出这种行为--因为bool是int的子类型。这是我在Python语言设计这一块缺失的洞察力。 - opatut

0

因为 int(False) == 0int(True) == 1。这就是 Python 在尝试评估 0 == False 时所做的。

另一方面,bool('') == False。对于 bool([])bool({}) 也是如此。

x 评估为 True 并不意味着 x == True


如果你把事情搞反了呢?例如:False == 0它是在执行 False == bool(0) 吗?如果是这样的话,那么它应该对空字符串执行相同的操作,但实际上并没有这样做。 - Tony Power
这就是为什么在检查布尔值时应该使用 is 而不是 == 的原因,我不明白这个推论的逻辑。 - khelwood
测试 x is Truex is False 对于大多数的 x 值来说都是 False,因此你建议使用 is 是非常错误的。 - holdenweb
此外,了解所使用的机制。解释器将bool函数应用于值。bool返回TrueFalse - holdenweb

0

如果你想要查看官方解释,只需像这样转换你的值:

print(bool(None) == False)
print(False == False)
print(bool(0) == False)
print(bool(0.0) == False)
print(bool(0j) == False)
print(bool('') == False)
print(bool(()) == False)
print(bool([]) == False)
print(bool({}) == False)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接