链(* iter)与chain.from_iterable(iter)

时间:2016-09-16 13:44:42

标签: python

我对itertools中所有有趣的迭代器非常着迷,但我遇到的一个困惑是这两个函数之间的区别以及为什么存在chain.from_iterable。

from itertools import chain

def foo(n):
    for i in range(n):
        yield [i, i**2]

chain(*foo(5))

chain.from_iterable(foo(5))

这两个功能有什么区别?

3 个答案:

答案 0 :(得分:10)

前者只能处理无包装的迭代。后者可以处理无法完全解压缩的迭代,例如无限生成器。

考虑

>>> from itertools import chain
>>> def inf():
...     i=0
...     while True:
...         i += 1
...         yield i
... 
>>> x=inf()
>>> y=chain.from_iterable(x)
>>> z=chain(*x)
<hangs forever>

此外,只是解压缩的行为是一项急切的,前期成本活动,因此如果您的迭代具有您想要懒惰评估的效果,from_iterable是您的最佳选择。

答案 1 :(得分:8)

chain(*foo(5))解包整个生成器,将其打包成一个元组并进行处理。

chain.from_iterable(foo(5))查询从foo(5)值创建的生成器的值。

尝试foo(1000000)并观察内存使用率是否上升。

答案 2 :(得分:4)

*解包迭代器,这意味着迭代迭代器以将其值传递给函数。 chain.from_iterable懒惰地逐个迭代迭代器。