为什么用 "是 "来做布尔比喻如此可怕?

问题描述 投票:1回答:1

样式指南中写道。

# 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 构。

显然,PEP的建议有一个很好的理由,但它是什么呢?

在评论者的提示下,进一步的研究使我有了以下发现。

if x:

调用x类的__bool方法 该方法应该返回True或False 取决于对象认为自己是哪一个.

if x==True:

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

if x is True

既不调用。这将测试 x 是否是 "True "对象。它完全规避了 __eq 和 __bool 方法。

注意:我不是在问关于 ==is. 如果这就是你来这里的原因,请看一下。"=="和 "is "有区别吗?

python
1个回答
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 并不是唯一的布尔类型。库可以自由定义自己的类型。flag 的一个实例。numpy.bool_,它是一个不同的对象 True. (NumPy这样做有一个很好的理由--使用他们自己的布尔类型可以让他们对0维值的处理更加统一。这也是NumPy也有自己的数值标量类型的原因)。)

另外。is True 甚至在你的例子中都没有发现问题。它只是把一个沉默的错误行为换成了另一个。f("False") 打印 doit 是个问题,但也是 f("True") 默默地什么都不做。两个版本的测试都没有产生实际的错误信息。


4
投票

为什么会这样呢?

因为它在逻辑上是错误的,一个 类别错误. 随着 is 你明确地执行了一个身份检查,一个参考比较。但这不是你 打算 在这里做。的 意图 的代码是为了检查一个值是否为真值(或者,更严格的说。True). 该值是否与常量 True 不仅是无关紧要的,而且是主动分散注意力的。

换句话说,该守则的意图是涉及到 价值 的表达方式,所以检查其 价值,而不是其 参考身份.

© www.soinside.com 2019 - 2024. All rights reserved.