Home > database >  Unpacking array as a zip function argument
Unpacking array as a zip function argument

Time:04-03

I've met some kind of problem during my python journey. According to Python iterator and zip post, the upvoded answers says that:

*[iter(a)] * 2

is the same thing as

 *[iter(a), iter(a)]

which i dont think seems to be correct. For example: If I'll use zip function in first case: The iterator's memory location will be the same so the array a will be grouped in tuples of two items.

In the second case The two same arrays will be just zipped. Why is that? Whats the flow. In my opinion in first case iter method is called once and then it is just copied to the second place in list.

In second case, the iter method iter is called twice. Here is my piece of code:

a = list(range(10))

def zippo(a, b):
    temp = []
    x1 = iter(a)
    x2 = iter(b)
    while True:
        try:
            item_1 = next(x1)
            item_2 = next(x2)
            temp.append((item_1, item_2))
        except StopIteration:
            break
    return temp


def iter_returner(lis_t):
    temp = iter(lis_t)
    print(temp)
    return temp


print(zippo(*[iter_returner(a)] * 2))
print(zippo(*[iter_returner(a), iter_returner(a)]))

Here is the output:

<list_iterator object at 0x000001BC11A70FD0>
[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]
<list_iterator object at 0x000001BC11A70FD0>
<list_iterator object at 0x000001BC11A70FA0>
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9)]

Are my thoughts correct? What is the flow in these two cases?

CodePudding user response:

iter(a) returns a new, mutable, iterator over a that is independent of existing iterators.

some_list * some_integer returns a new list that contains the items of some_list repeated some_integer times. Mutable objects are not copied, but multiple entries of the new list will point to the exact same object.

zip(*[iter(a), iter(a)]) is equivalent to zip(iter(a), iter(a)), which is equivalent to zip(a, a) (because zip calls iter on its argument), and

for x, y in zip(a, a):
   ...

is equivalent to

for x in a:
   y = x
   ...

On the other hand, zip(*[iter(a)] * 2) is equivalent to first doing it = iter(a) and then calling zip(it, it), which, as you have observed, basically splits the input list into pairs.

The important difference is that iterators are mutable objects, and calling next on an iterator mutates that iterator.

The name(s) you give that iterator does not matter.

it1 = iter(a)
next(it1)
next(it1)

... does the same thing as:

it2 = it1 = iter(a)
next(it1)
next(it2)

... but if you do:

it1 = iter(a)
it2 = iter(a)
next(it1)
next(it2)

... you have two different iterators that both get advanced only once.

  • Related