我在Python(3.3)中使用过滤器功能。我试图将过滤器对象转换为列表。这就是我发现的:
>>> a=['1', '2', '3', None]
>>> b=filter(None,a)
>>> list(b)
['1', '2', '3']
>>> list(b)
[]
这对我来说很奇怪。谁能解释一下呢?
答案 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
,经常浪费内存并在构建中间列表对象时循环然后在迭代后再次丢弃。通过返回迭代器,实现列表的选择取决于程序员。