为什么布尔值与“is”的比较如此糟糕?

2024-05-15 11:53:52 发布

您现在位置:Python中文网/ 问答频道 /正文

样式指南如下:

# Correct:
if greeting:

# Wrong:
if greeting == True:

# Worse:
if greeting is True:

PEP 8,搜索“更糟”一词

为什么会这样?我习惯于尽可能明确地检查条件,使代码更具可读性,并捕捉异常

考虑这个函数:

def f(do_it):
   if do_it : print("doit")
   else : print("no don't") 

很容易滥用/监督,行为出人意料

>>> f("False")
doit
>>> f([False])
doit

例如,当您检查可能无意中传递if子句的返回值时,这是一个真正的问题。这可以通过使用is构造来避免

显然,政治公众人物的推荐有很好的理由,但它是什么

在评论者的推动下,进一步的研究使我得出以下结论:

if x:

调用x类的_bool方法。该方法应该返回True或False,这取决于对象认为自己是这两个对象中的哪一个

if x==True:

调用x类的_eq方法。该方法应该能够将自身与True(或False)进行比较,并根据具体情况返回True或False

if x is True

两者都不起作用。这将测试x是否为“真”对象。它完全绕过了_eq和_bool方法

注意:我不是问==is之间的区别。如果这就是你来这里的原因,请参见Is there a difference between "==" and "is"?


Tags: 对象方法falsetrueifis指南it
2条回答

在理论层面上,is表达了错误的东西。我们关心的是价值的真实性,而不是身份。在我们确实关心身份的少数情况下,is比较是合适的

在实践层面上,is True甚至没有按照人们期望的方式工作:

In [1]: import numpy

In [2]: x = numpy.array([1, 2, 3])

In [3]: flag = x[0] == 1

In [4]: flag
Out[4]: True

In [5]: if flag: print('true')
true

In [6]: if flag is True: print('true')

In [7]:

我们将1与1进行比较,得到一个看起来像True的东西,但是is比较失败。这是因为bool不是唯一的布尔类型。图书馆可以自由定义自己的图书馆flagnumpy.bool_的一个实例,它与True是不同的对象。(NumPy有一个很好的理由——使用它们自己的布尔类型可以让它们提供更统一的0维值处理。这也是NumPy也有自己的数值标量类型的原因。)

而且,is True在您的示例中甚至没有发现问题。它只是把一种无声的错误行为转换成另一种f("False")打印{}是一个问题,但是{}默默地什么也不做也是一个问题。两个版本的测试都不会产生实际的错误消息

Why is this?

因为它在逻辑上是错误的,a category mistake。使用is可以显式执行身份检查,即引用比较。但这不是你在这里想要做的。代码的意图是检查值是否真实(或者更严格地说,True)。该值是否恰好与常量True位于内存中的同一地址不仅无关紧要,而且会让人分心

换句话说,代码的意图涉及表达式的,因此检查其,而不是其参考标识

相关问题 更多 >