Python列表迭代器行为和next(iterator)

问题:Python列表迭代器行为和next(iterator)

考虑:

>>> lst = iter([1,2,3])
>>> next(lst)
1
>>> next(lst)
2

因此,按预期方式,通过更改同一对象来处理迭代器。

在这种情况下,我希望:

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

跳过每第二个元素:对的调用next应使迭代器前进一次,然后循环进行的隐式调用应使它第二次前进-并将第二次调用的结果分配给i

没有。该循环将打印列表中的所有项目,而不会跳过任何项目。

我的第一个想法是,可能会发生这种情况,因为循环会调用iter它所传递的内容,并且这可能会提供一个独立的迭代器-事实并非如此iter(a) is a

那么,为什么next在这种情况下似乎不推进迭代器呢?

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?


回答 0

您看到的是,解释器next()除了回显i每次迭代外,还回显了返回值:

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

所以,0是的输出print(i)1从返回值next(),通过交互式解释回荡,等,有仅5次迭代,产生2行每次迭代被写入到所述终端。

如果您分配next()事物的输出按预期工作:

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

或打印额外的信息来区分print()从交互式解释回声输出:

>>> 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

换句话说,next()它按预期方式工作,但是由于它从迭代器返回下一个值,并由交互式解释器回显,因此您被认为是循环以某种方式拥有自己的迭代器副本。

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.


回答 1

发生的是 next(a)返回a的下一个值,该值将打印到控制台,因为它不受影响。

您可以做的就是使用此值影响变量:

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

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

回答 2

我觉得现有的答案有点令人困惑,因为他们只间接地表明了代码示例基本神秘的事: *“打印我”和“未来(一)”是导致他们的结果进行打印。

由于他们正在打印原始序列的交替元素,并且“ next(a)”语句正在打印是意外的,因此看起来“ print i”语句正在打印所有值。

鉴于此,变得更加清楚的是,将“ next(a)”的结果分配给变量会禁止打印其结果,从而仅打印“ i”循环变量的替代值。同样,使“打印”语句发出更独特的内容也可以消除歧义。

(现有答案之一反驳其他答案,因为该答案会将示例代码评估为一个块,因此解释器不会报告“ next(a)”的中间值。)

通常,在回答问题时令人着迷的事情是,一旦您知道答案,就应明确表述哪些是显而易见的。可能难以捉摸。一旦理解了答案,就同样会提出批评。这真有趣…

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…


回答 3

您的Python /计算机出了点问题。

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

>>> 
0
2
4
6
8

像预期的那样工作。

在Python 2.7和Python 3+中进行了测试。两者均可正常工作

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


回答 4

对于那些仍然不了解的人。

>>> 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

正如其他人已经说过的那样,next将迭代器按预期方式增加1。将其返回值分配给变量不会神奇地改变其行为。

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.


回答 5

如果作为函数调用,它将表现出您想要的方式:

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

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