chain(*iterable) 与 chain.from_iterable(iterable) 之间的区别
Difference between chain(*iterable) vs chain.from_iterable(iterable)
我一直对 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))
这两个函数有什么区别?
chain(*foo(5))
解压整个生成器,将其打包成一个元组并进行处理。
chain.from_iterable(foo(5))
查询从 foo(5)
值创建的生成器中的值。
尝试 foo(1000000)
并观察内存使用量不断上升。
*
解包迭代器,这意味着它迭代迭代器以便将其值传递给函数。 chain.from_iterable
懒惰地逐一迭代迭代器。
前者只能处理不可打包的迭代。后者可以处理不能完全解包的iterables,比如infinite generators。
考虑
>>> from itertools import chain
>>> def inf():
... i=0
... while True:
... i += 1
... yield (i, i)
...
>>> x=inf()
>>> y=chain.from_iterable(x)
>>> z=chain(*x)
<hangs forever>
此外,仅拆包这一行为是一项急切的前期成本 activity,因此如果您的迭代器具有您想延迟评估的效果,from_iterable
是您的最佳选择。
我一直对 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))
这两个函数有什么区别?
chain(*foo(5))
解压整个生成器,将其打包成一个元组并进行处理。
chain.from_iterable(foo(5))
查询从 foo(5)
值创建的生成器中的值。
尝试 foo(1000000)
并观察内存使用量不断上升。
*
解包迭代器,这意味着它迭代迭代器以便将其值传递给函数。 chain.from_iterable
懒惰地逐一迭代迭代器。
前者只能处理不可打包的迭代。后者可以处理不能完全解包的iterables,比如infinite generators。
考虑
>>> from itertools import chain
>>> def inf():
... i=0
... while True:
... i += 1
... yield (i, i)
...
>>> x=inf()
>>> y=chain.from_iterable(x)
>>> z=chain(*x)
<hangs forever>
此外,仅拆包这一行为是一项急切的前期成本 activity,因此如果您的迭代器具有您想延迟评估的效果,from_iterable
是您的最佳选择。