python - 为什么与“是”的布尔比较如此可怕?
问题描述
风格指南如下:
# Correct:
if greeting:
# Wrong:
if greeting == True:
# Worse:
if greeting is True:
参见PEP 8,搜索单词“worse”
为什么是这样?我习惯于尽可能明确地检查条件,使代码更具可读性,并捕捉异常。
考虑这个函数:
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”之间有区别吗?
解决方案
为什么是这样?
因为它在逻辑上是错误的,类别错误。随着is
您明确地执行身份检查,参考比较。但这不是你打算在这里做的。代码的目的是检查一个值是否为真(或更严格地说,是True
)。该值是否恰好与常量位于内存中的同一地址True
不仅无关紧要,而且会分散注意力。
换句话说,代码的意图与表达式的值有关,因此检查它的值,而不是它的引用标识。
推荐阅读
- javascript - 如何在启用 shadow dom 模式的 vuejs 中加载样式?
- c# - 有没有办法在 Blazor WebAssembly 客户端上使用 MSAL.NET 为单点登录提供域提示?
- react-native - 在本机反应中根据视图高度更改页脚样式
- java - 无法将文件写入 Documents 文件夹
- kubernetes - 为什么使用 kubernetes yaml 文件无法重现 podman pod?
- javascript - 无需用户交互即可将文件 url 链接复制到剪贴板的 Javascript
- javascript - 如果没有匹配的累加器,RxJS 如何减少?
- javascript - Reactjs - 使用功能组件在应用程序启动时调用函数
- ios - 代理背后的 XCode Swift 包管理器错误
- json - JSONSchema 本身是否有 JSONSchema?