【问题标题】:filter object becomes empty after iteration? [duplicate]迭代后过滤器对象变为空? [复制]
【发布时间】:2017-11-09 05:58:16
【问题描述】:

我正在学习如何使用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))

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

你能解释一下为什么吗?

【问题讨论】:

标签: python python-3.x


【解决方案1】:

这是一个经典的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的惰性评估带入图片时,就会出现问题。

【讨论】:

  • 哦,好吧,所以如果我想多次使用它,我只需将它保存在另一个变量中,比如 people3 = list(people2),对吗?
  • @L'ultimo 是的,你明白了。
  • 好的,非常感谢! :)
  • (或者更好的是我可以直接做people2 = filter(lambda x: "height" in x, people))
  • 我不明白这个的逻辑。 filter 和 map 是特殊对象,它们是否可以在解析后没有将其重置为开始的逻辑?您仍然可以进行惰性评估并且也可以多次使用。每次调用 iter 时,从头开始返回一个新的惰性迭代器。
【解决方案2】:

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

阅读本文了解更多详情 - Lazy evaluation python

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-08
    • 2018-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-04
    • 2014-03-15
    相关资源
    最近更新 更多