I have found below code in web, result is tuple of two elements in list, how to understand [iter(list)]*2?
lst = [1,2,3,4,5,6,7,8]
b=zip(*[iter(
iter(lst) turns a list into an iterator. Iterators let you step lazily through an iterable by calling next() until the iterator runs out of items.
[iter(lst)] puts the iterator into a single-element list.
[iter(lst)] * 2 makes 2 copies of the iterator in the list, giving
it = iter(lst)
[it, it]
Both list elements are aliases of the same underlying iterator object, so whenever next() is called on either of the iterators as zip exhausts them, successive elements are yielded.
*[...] unpacks the list of the two copies of the same iterator into the arguments for zip. This creates a zip object that lets you iterate through tuples of elements from each of its arguments.
list(...) iterates through the zip object and copies the elements into a list. Since both zipped iterators point to the same underlying iterator, we get the sequential elements seen in your output.
Without using the iterator alias, you'd get
>>> list(zip(iter(lst), iter(lst)))
[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8)]
A similar way to write list(zip(*[iter(lst)] * 2)) is list(zip(lst[::2], lst[1::2])), which seems a bit less magical (if much less performant).
The explanation for
>>> list(zip(*[iter(lst)] * 3))
[(1, 2, 3), (4, 5, 6)]
omitting elements is that the first time the zip object tries to yield a None result on any of the argument iterables, it stops and does not generate a tuple. You can use itertools.zip_longest to match your expected behavior, more or less:
>>> list(zip_longest(*[iter(lst)] * 3))
[(1, 2, 3), (4, 5, 6), (7, 8, None)]
See the canonical answer List of lists changes reflected across sublists unexpectedly if the [...] * 2 aliasing behavior is surprising.