Difference between chain(*iter) vs chain.from_iterable(iter)
<p>I have been really fascinated by all the interesting iterators in itertools and one confusion I have had is the difference between these two functions and why chain.from_iterator exists.</p>

<pre><code>from itertools import chain

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

chain(*foo(5))

chain.from_iterable(foo(5))
</code></pre>

<p>What is the difference between the two functions?</p>

<p><code>chain(*foo(5))</code> unpacks the whole generator, packs it into a tuple and processes it then.</p>

<p><code>chain.from_iterable(foo(5))</code> queries the generator created from <code>foo(5)</code> value for value.</p>

<p>Try <code>foo(1000000)</code> and watch the memory usage go up and up.</p>

python