我在 Python (3.3) 中使用 filter 函数。我试图将过滤器对象转换为列表。这就是我发现的:
>>> a=['1', '2', '3', None]
>>> b=filter(None,a)
>>> list(b)
['1', '2', '3']
>>> list(b)
[]
这对我来说很奇怪。谁能解释一下?
我在 Python (3.3) 中使用 filter 函数。我试图将过滤器对象转换为列表。这就是我发现的:
>>> a=['1', '2', '3', None]
>>> b=filter(None,a)
>>> list(b)
['1', '2', '3']
>>> list(b)
[]
这对我来说很奇怪。谁能解释一下?
在 Python 3 中,filter()
返回一个迭代器类型,并且像所有迭代器一样,只能迭代一次。迭代器filter()
按需过滤值,它在内存中不保存任何过滤值。
您可以对列表迭代器执行相同的操作,返回iter()
:
>>> a = [1, 2, 3]
>>> b = iter(a)
>>> list(b)
[1, 2, 3]
>>> list(b)
[]
发生这种情况是因为迭代器的.__next__()
方法预计会StopIteration
在耗尽后引发,然后必须始终StopIteration
从那里引发:
一旦迭代器的
__next__()
方法 raiseStopIteration
,它必须在后续调用中继续这样做。不遵守此属性的实现被视为已损坏。
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()
函数调用.__next__()
迭代器方法,并传播引发的异常;list()
另一方面,迭代 until StopIteration
,捕获该异常并返回它设法接收的任何元素的列表。
为了完整起见,在 Python 2 中,filter()
(以及许多其他内置函数和方法)返回 a list
,通常会浪费内存和循环来构建中间列表对象,然后在迭代后再次丢弃该对象。通过返回一个迭代器,实现列表的选择由程序员决定。