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.