我正在学习如何使用
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))
第二次,我得到一个空列表。
你能解释一下为什么吗?
这是一个经典的 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 的惰性求值引入图片中时,问题就出现了。
这是因为过滤器真正返回的是一个迭代器。 在您开始使用其结果之前,此迭代器实际上不会执行任何操作 - 在本例中,当您将其转换为列表时。
people2
是准备过滤人员列表的东西;然后,当对其调用 list 时,它会迭代人员列表并提供过滤后的结果。 现在迭代器已经完成,没有什么可以迭代的了,所以当你第二次调用 list 时,那里什么也没有了。
阅读本文了解更多详细信息 - Python 中的惰性求值