列出两次过滤器对象将返回一个空白列表?

时间:2013-11-03 22:58:08

标签: python python-3.x iterator

我在Python(3.3)中使用过滤器功能。我试图将过滤器对象转换为列表。这就是我发现的:

>>> a=['1', '2', '3', None]
>>> b=filter(None,a)
>>> list(b)
['1', '2', '3']
>>> list(b)
[]

这对我来说很奇怪。谁能解释一下呢?

1 个答案:

答案 0 :(得分:8)

在Python 3中,filter()返回iterator type,与所有迭代器一样,只能迭代一次。 filter()迭代器按需过滤值,它不会在内存中保存任何过滤值。

您可以对iter()返回的列表迭代器执行相同的操作:

>>> a = [1, 2, 3]
>>> b = iter(a)
>>> list(b)
[1, 2, 3]
>>> list(b)
[]

这是因为迭代器的.__next__() method一旦耗尽就会引发StopIteration,然后必须总是从那里引出StopIteration

  

一旦迭代器的__next__()方法引发StopIteration,它必须在后续调用中继续这样做。不遵守此属性的实现被视为已损坏。

filter()正确执行此操作:

>>> a = [1, 2, 3, None]
>>> b = filter(None, a)
>>> list(b)
[1, 2, 3]
>>> next(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

这里next() function调用.__next__()迭代器方法,并传播引发的异常;另一方面,list()迭代到StopIteration,捕获该异常并返回它设法接收的任何元素的列表。

为了完整起见,在Python 2中,filter()(以及许多其他内置函数和方法)返回list,经常浪费内存并在构建中间列表对象时循环然后在迭代后再次丢弃。通过返回迭代器,实现列表的选择取决于程序员。