将“a == True:”简化为“a”——这是个好主意吗?

Posted

技术标签:

【中文标题】将“a == True:”简化为“a”——这是个好主意吗?【英文标题】:Simplifying "a == True:" to "a" - is it a good idea? 【发布时间】:2021-11-03 20:14:45 【问题描述】:

PEP8 建议应简化以下代码。

原版

if a == True:

建议

if a:

但是,这两者并不相同。当我遵循 PEP8 建议时,我发现了这一点。试试下面的代码

import numpy as np
a = np.nan

if a == True:
    print('a is True')
else:
    print('a is not True')
    
if a:
    print('a is True')
else:
    print('a is not True')

你会发现第一个告诉 a 不正确(正确),而第二个错误告诉 a 是真的。

a is not True
a is True

这个误导性建议的意义何在?

【问题讨论】:

如果您正在使用可能值为Truenp.nan 的变量,那么这是您的设计问题,而不是布尔比较。 if 声明检查数据的真实性。您应该始终了解数据的一般形状。如果数据是一个列表,if 会检查它是否为空。如果数据是布尔值,if 会检查它是否为真。 Python 程序员一眼就能看出这些意图。 == True 只是混淆了这一点,并使惯用的 Python 编码人员认为正在发生一些非常可疑的事情。 您的问题是类型不匹配。 a 是布尔值还是数字?您将 nan 分配给它,它具有真实性值。当您说a = np.nan; if a 时,您是在说“a 是否有价值”。 (它确实是 nan 的值。)通常,如果将值分配给未明确为 False、None、0 或空的名称,您可以期望真值评估将其视为“True”。此外,由于您在询问if a == True 时没有指定a = True,因此您会得到错误的结果。就像你问if 2 == True一样。 nan 不是 True - 它甚至不是布尔值。 PEP8 建议从根本上假设您了解 Python 的真值测试语义,here is the relevant documentation 在这种情况下,np.nan 是真的。为什么你不这么认为 非常感谢您的良好反馈。不过,我认为建议用不产生相同结果的东西来简化短语有点问题。 Matti:definition 的“真实性”表明看似真实的品质与逻辑、事实证据等无关。 【参考方案1】:

您误读了 PEP8 风格指南。这是相关部分(强调我的):

不要使用 == 将 boolean 值与 True 或 False 进行比较:

# Correct:
if greeting:
# Wrong:
if greeting == True:

由于np.nan 不是布尔值,因此此建议不适用。

请注意,如果您将数值与True 进行比较,那么您通常首先做错了什么。数值 11.0 都等于 True,所以如果你有一个变量可以是数字或布尔值,这个测试可能会给你意想不到的结果。拥有一个可以是布尔值或非布尔值的变量通常也是一种反模式。

【讨论】:

【参考方案2】:

首先,np.nan 的工作方式与 float('nan') 相同。

import numpy as np
print(type(np.nan))  # <class 'float'>

Python 通常says:

默认情况下,一个对象被认为是true,除非它的类定义了 返回 False 的 __bool__() 方法或 __len__() 方法 使用对象调用时返回零。

然后对于内置数字类型,它说任何零都被认为是False

任何数字类型的零:0、0.0、0j、Decimal(0)、Fraction(0, 1)

当我将唯一的浮点类型加粗为 False 时,任何其他浮点数都被视为True

所以:

print(bool(float('nan')))   # True

Numpy 的行为也与 python 一样。

当您说if obj: 时,python 试图通过bool() 的帮助来获取obj 的真值,这确实查看了__bool____len__ 特殊方法。 (__bool__ 如果实施,优先级更高)。

【讨论】:

"np.nan 的工作方式与 float('nan')" 当然,因为 np.nan *是与 float('nan') 具有相同类型值的相同类型的对象. "当你说 if obj: 时,它会变成 if bool(obj) is True: 不,python 会这样做。Numpy 无法控制这种行为。实际上,主要的 numpy 类型,np.ndarray抛出一个错误。因为numpy.ndarray.__bool__ 引发了一个错误(除非你正在使用一个带有一个元素的numpy.ndarray,令人困惑) @juanpa.arrivillaga 是的,在这两种情况下它都会抛出一个 ValueError ,我的意思是 (if arr:) 和 bool(arr) @juanpa.arrivillaga 不是因为if arr: 试图在arr 上调用bool() 吗? 正因为如此。让我准确地说,条件语句的机制,例如if something: 被处理是解释器运行时的一部分,即语言本身。本质上,使用了bool(something)len(something),对象可以决定如何使用特殊的方法钩子来响应它,__bool____len__ 我并不反对你的回答,只是建议一种改写方式让它更清楚。【参考方案3】:

我建议使用显式条件。如果 a!=0,第二个选项将始终为您提供 True,此外,当您不编写代码时,这种类型的条件会令人困惑。

【讨论】:

【参考方案4】:

这意味着变量a 的值是否等于True

if a == True:

但是这个变量a有没有值。

if a:

【讨论】:

以上是关于将“a == True:”简化为“a”——这是个好主意吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 3-SAT 简化为独立集?

编译器是不是将给定常量参数的简单函数简化为唯一指令?

SSE2:如何将 _m128 简化为一个单词

将嵌套数组简化为单级数组[重复]

将对象数组的数组简化为对象数组

将 3 个案例陈述合并或简化为一个