在布尔值列表中使用列表解析时出现意外结果

时间:2018-05-25 17:15:08

标签: python boolean list-comprehension

r=[True, False,True,False, False]
print([i for i in r if str(r[i])=="True"])

此代码给出以下意外结果: [假,假,假]

为什么这是行为?我希望: [True,True]

5 个答案:

答案 0 :(得分:11)

i是一个值为TrueFalse的布尔值。如果您在r[i]中将其用作索引,则会得到r[0]r[1],因为boolint的子类。

您可以将其描绘为r[int(i)]int(True) == 1int(False) == 0

你的意思是:

print([i for i in range(len(r)) if str(r[i])=="True"])

其中i是整数或:

print([i for i in r if str(i)=="True"])

其中i是布尔值。

请注意,如果i是布尔值,if str(i) == "True"中几乎没有意义。更简洁的写作方式是:

print([i for i in r if i])

甚至使用filter内置函数:

it = filter(None, r)
print(list(it))

答案 1 :(得分:2)

您的意思是str(i)

使用原始代码

  • 在第一次迭代时,iTrue,而True的整数值为1r[i]将为{{1}这是假的。 r[1]条件失败。

  • 在第二次迭代中,ifi,而False的整数值为False0将为{{1}这是真的。 r[i]条件成功,i(r[0])被添加到结果中。

答案 2 :(得分:2)

您以两种不同的方式使用i

  • 索引列表(r[i]
  • 并且作为列表理解中的迭代变量[i for i in items]
如果r[i]不是整数,

i通常会失败 - 列表只能通过整数索引。但是,布尔值是Python中的一个特例,bool实际上是int的子类:

>>> issubclass(bool, int)
True
>>> isinstance(True, int)
True

这就是为什么这甚至“有效”,并给你惊人的结果。

由于不需要在列表推导中使用列表索引,这就是你可能要编写的内容:

>>> print([i for i in r if str(i) == "True"])
[True, True]

另请注意,此处没有隐含的投射,与之前建议的其他答案不同:

Python不会这样做。它确实“将r [i]翻译为r [int(i)]”。

让我们看一下字符串"1"。如果你要求它,它会愉快地把它投射到int

>>> int("1")
1

但是,使用"1"进行列表索引将永远不会起作用:

>>> lst = ['a', 'b', 'c']
>>> lst["1"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not str

您的示例仅“有效”,因为bool实际上 int的子类,而True因此整数,就Python而言。

答案 3 :(得分:2)

这可以为您提供所需的输出

r=[True, False,True,False, False]
print([i for i in r if str(i)=="True"])

我指的是数组中的各个元素。

答案 4 :(得分:1)

Jacques Gaudin是正确的,您正在使用布尔值进行索引。然而,更简单的代码版本是:

print([i for i in r if str(i)=="True"])

或者,当然:

print([i for i in r if i])