The difference between a chain (* iter) and a chain. Cancelable (iterator)

I was really fascinated by all the interesting iterators in itertools, and the one confusion I had was the difference between the two functions and why the .from_iterator chain exists.

from itertools import chain def foo(n): for i in range(n): yield [i, i**2] chain(*foo(5)) chain.from_iterable(foo(5)) 

What is the difference between the two functions?

+8
python
source share
3 answers

The first can only handle unpacked iterations. The latter can handle iterations that cannot be completely unpacked, for example, infinite generators.

Consider

 >>> 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> 

In addition, only the act of unpacking is impatient activity before starting work, so if your iterative effect has an effect that you want to evaluate lazily, from_iterable is your best option.

+8
source share

chain(*foo(5)) unpacks the entire generator, packs it into a tuple, and processes it.

chain.from_iterable(foo(5)) queries the generator created from foo(5) for the value.

Try foo(1000000) and make sure that memory usage is increasing and increasing.

+6
source share

* unpacks the iterator, that is, it iterates the iterator to pass its values ​​to the function. chain.from_iterable through the iterator one by one lazily.

+3
source share

All Articles