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

P20*_*000 4 python boolean boolean-expression

风格指南如下:

# Correct:
if greeting:

# Wrong:
if greeting == True:

# Worse:
if greeting is True:
Run Code Online (Sandbox Code Playgroud)

请参阅PEP 8,搜索单词“更糟”

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

考虑这个函数:

def f(do_it):
   if do_it : print("doit")
   else : print("no don't") 
Run Code Online (Sandbox Code Playgroud)

很容易被滥用/监督,出现意想不到的行为

>>> f("False")
doit
>>> f([False])
doit
Run Code Online (Sandbox Code Playgroud)

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

显然,PEP 建议有充分的理由,但它是什么?

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

if x:
Run Code Online (Sandbox Code Playgroud)

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

if x==True:
Run Code Online (Sandbox Code Playgroud)

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

if x is True
Run Code Online (Sandbox Code Playgroud)

两者都不调用。这测试 x 是否是“True”对象。它完全绕过了 __eq 和 __bool 方法。

==注意:我不是在问和之间的区别is。如果这就是您来到这里的原因,请参阅“==”和“is”之间有区别吗?

Kon*_*lph 5

\n

为什么是这样?

\n
\n\n

因为它\xe2\x80\x99在逻辑上是错误的,属于类别错误。您正在is明确执行身份检查、参考比较。但 \xe2\x80\x99 不是您打算在这里执行的操作。代码的目的是检查一个值是否为真(或者更严格地说,True。该值是否恰好与常量驻留在内存中的同一地址True不仅无关紧要,而且它\xe2\x80\x99 会让人分心。

\n\n

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

\n