Python list iterator behavior and next(iterator)

PythonListIteratorIteration

Python Problem Overview


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?

Python Solutions


Solution 1 - Python

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.

Solution 2 - Python

What is happening is that next(a) returns the next value of a, which is printed to the console because it is not affected.

What you can do is affect a variable with this value:

>>> a = iter(list(range(10)))
>>> for i in a:
...    print(i)
...    b=next(a)
...
0
2
4
6
8

Solution 3 - Python

I find the existing answers a little confusing, because they only indirectly indicate the essential mystifying thing in the code example: both* the "print i" and the "next(a)" are causing their results to be printed.

Since they're printing alternating elements of the original sequence, and it's unexpected that the "next(a)" statement is printing, it appears as if the "print i" statement is printing all the values.

In that light, it becomes more clear that assigning the result of "next(a)" to a variable inhibits the printing of its' result, so that just the alternate values that the "i" loop variable are printed. Similarly, making the "print" statement emit something more distinctive disambiguates it, as well.

(One of the existing answers refutes the others because that answer is having the example code evaluated as a block, so that the interpreter is not reporting the intermediate values for "next(a)".)

The beguiling thing in answering questions, in general, is being explicit about what is obvious once you know the answer. It can be elusive. Likewise critiquing answers once you understand them. It's interesting...

Solution 4 - Python

For those who still do not understand.

>>> a = iter(list(range(10)))
>>> for i in a:
...    print(i)
...    next(a)
... 
0 # print(i) printed this
1 # next(a) printed this
2 # print(i) printed this
3 # next(a) printed this
4 # print(i) printed this
5 # next(a) printed this
6 # print(i) printed this
7 # next(a) printed this
8 # print(i) printed this
9 # next(a) printed this

As others have already said, next increases the iterator by 1 as expected. Assigning its returned value to a variable doesn't magically changes its behaviour.

Solution 5 - Python

Something is wrong with your Python/Computer.

a = iter(list(range(10)))
for i in a:
   print(i)
   next(a)

>>> 
0
2
4
6
8

Works like expected.

Tested in Python 2.7 and in Python 3+ . Works properly in both

Solution 6 - Python

It behaves the way you want if called as a function:

>>> def test():
...     a = iter(list(range(10)))
...     for i in a:
...         print(i)
...         next(a)
... 
>>> test()
0
2
4
6
8

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionlvcView Question on Stackoverflow
Solution 1 - PythonMartijn PietersView Answer on Stackoverflow
Solution 2 - Pythonnjzk2View Answer on Stackoverflow
Solution 3 - PythonklmView Answer on Stackoverflow
Solution 4 - PythonWesleyView Answer on Stackoverflow
Solution 5 - PythonInbar RoseView Answer on Stackoverflow
Solution 6 - PythonburmerView Answer on Stackoverflow