Consider:
>>> lst = iter([1,2,3])
>>> next(lst)
1
>>> next(lst)
2
So, advancing the iterator is, as expected, handled by mutating that same object.
This being the case, I would expect:
a = iter(list(range(10)))
for i in a:
print(i)
next(a)
to skip every second element: the call to next
should advance the iterator once, then the implicit call made by the loop should advance it a second time - and the result of this second call would be assigned to i
.
It doesn't. The loop prints all of the items in the list, without skipping any.
My first thought was that this might happen because the loop calls iter
on what it is passed, and this might give an independent iterator - this isn't the case, as we have iter(a) is a
.
So, why does next
not appear to advance the iterator in this case?
What you see is the interpreter echoing back the return value of next()
in addition to i
being printed each iteration:
>>> a = iter(list(range(10)))
>>> for i in a:
... print(i)
... next(a)
...
0
1
2
3
4
5
6
7
8
9
So 0
is the output of print(i)
, 1
the return value from next()
, echoed by the interactive interpreter, etc. There are just 5 iterations, each iteration resulting in 2 lines being written to the terminal.
If you assign the output of next()
things work as expected:
>>> a = iter(list(range(10)))
>>> for i in a:
... print(i)
... _ = next(a)
...
0
2
4
6
8
or print extra information to differentiate the print()
output from the interactive interpreter echo:
>>> a = iter(list(range(10)))
>>> for i in a:
... print('Printing: {}'.format(i))
... next(a)
...
Printing: 0
1
Printing: 2
3
Printing: 4
5
Printing: 6
7
Printing: 8
9
In other words, next()
is working as expected, but because it returns the next value from the iterator, echoed by the interactive interpreter, you are led to believe that the loop has its own iterator copy somehow.