我正在学习如何使用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))
第二次,我得到一个空列表。
你能解释一下为什么吗?
答案 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