迭代后过滤器对象变空?

时间:2017-06-07 18:22:42

标签: python python-3.x

我正在学习如何使用filter函数。

这是我写的代码:

people = [{'name': 'Mary', 'height': 160},
          {'name': 'Isla', 'height': 80},
          {'name': 'Sam'}]

people2 = filter(lambda x: "height" in x, people)

正如您所看到的,我要删除所有不包含'height'键的词典。

代码工作正常,事实上如果我这样做:

print(list(people2))

我明白了:

[{'name': 'Mary', 'height': 160}, {'name': 'Isla', 'height': 80}]

问题在于,如果我这样做两次:

print(list(people2))
print(list(people2))

第二次,我得到一个空列表。

你能解释一下为什么吗?

2 个答案:

答案 0 :(得分:8)

这是一个经典的python3 doh!。

过滤器是一个可以迭代的特殊可迭代对象。但是,就像生成器一样,您只能迭代一次。因此,通过调用list(people2),您将迭代filter对象的每个元素以生成list。此时,您已到达可迭代的末尾,无需再返回。

因此,当您再次呼叫list(people2)时,您会得到一个空列表。

演示:

>>> l = range(10)
>>> k = filter(lambda x: x > 5, l)
>>> list(k)
[6, 7, 8, 9]
>>> list(k)
[]

我应该提一下,使用python2,filter会返回一个列表,所以你不会遇到这个问题。当你将py3的懒惰评估带入图片时会出现问题。

答案 1 :(得分:1)

这是因为过滤器真正转向的是迭代器。在你开始使用它的结果之前,这个迭代器并没有真正做任何事情,在这种情况下你把它投射到列表中。 people2这个东西已经准备好过滤人员列表,然后当列表被调用时,它会遍历人员列表并提供过滤结果。现在迭代器已经完成,没有什么东西可以迭代了,所以当你第二次调用list时,那里什么都没有。

阅读本文以获取更多详细信息 - Lazy evaluation python