我正在尝试更熟悉itertools
模块,并找到了一个名为ifilter
的函数。
根据我的理解,它基于给定的函数进行过滤和迭代,并在包含函数求值为True
的iterable元素的列表上返回一个迭代器。
问题1 :到目前为止我的理解是否正确?
问题2 :除了返回和迭代器之外,它与内置filter
函数有什么不同?
问题3 哪个更快?
据我所知,事实并非如此。我错过了什么吗? (我进行了以下测试)
>>> itertools.ifilter(lambda x: x%2, range(5))
<itertools.ifilter object at 0x7fb1a101b210>
>>> for i in itertools.ifilter(lambda x: x%2, range(5)): print i
...
1
3
>>> filter(lambda x: x%2, range(5))
[1, 3]
>>> function = lambda x: x%2
>>> [item for item in range(5) if function(item)]
[1,3]
答案 0 :(得分:19)
您的理解是正确的:唯一的区别是ifilter
返回迭代器,而使用filter
就像调用:
list(ifilter(...))
您可能也对PEP 289关于过滤器和ifilter的说法感兴趣:
列表推导大大减少了对
filter()
和map()
的需求。同样,生成器表达式可以最大限度地减少对itertools.ifilter()
和itertools.imap()
的需求。 [...]
另请注意,ifilter
在Python-3中变为filter
(因此从itertools中删除)。
答案 1 :(得分:14)
下面的示例包括一个数字生成器,它在产生数字之前立即打印消息,显示filter()
首先构建列表的方式,然后运行并过滤它。尽管itertools.ifilter
过滤了,但从不构建列表。如果您要过滤500,000个重要内容,则需要ifilter
,因此您不需要构建列表。
import itertools
def number_generator():
for i in range(0, 3):
print "yield", i
yield i
print "stopping"
function = lambda x: x > 0
numbers = number_generator()
print "itertools.ifilter:"
for n in itertools.ifilter(function, numbers):
print n
print "\nfilter:"
numbers = number_generator()
for n in filter(function, numbers):
print n
输出:
itertools.ifilter: yield 0 yield 1 1 yield 2 2 stopping filter: yield 0 yield 1 yield 2 stopping 1 2
答案 2 :(得分:3)
ifilter
返回一个生成器,而不是列表。
生成器在需要时动态创建项目,而不是先分配整个列表。这是ifilter
和filter
答案 3 :(得分:2)
在这里,您可以看到差异:
filter(function, iterable):从iterable的那些元素构造一个列表,函数返回true。
itertools.ifilter(predicate, iterable):制作一个iterator ,过滤来自iterable的元素,只返回谓词为True的元素。
这意味着要获取'ifiltered'项,您应该使用返回的迭代器进行迭代,但'filter'会返回列表中的所有元素,而不需要迭代。