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


147

考虑:

>>> 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在这种情况下似乎不推进迭代器呢?

Answers:


197

您看到的是,解释器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()它按预期方式工作,但是由于它从迭代器返回下一个值,并由交互式解释器回显,因此您被认为是循环以某种方式拥有自己的迭代器副本。


13
我不知道翻译器的这种行为。我很高兴在发现很多问题并解决一些实际问题之前发现了这一点。
brandizzi

5
... *死*。最糟糕的是,我记得一个星期前曾向某人确切提到过这种口译员的行为。
lvc

有趣。我在a:next(a)中为i尝试过;打印i并认为我会跳到1并打印1,3,5,7,9。但是仍然是0,2,4,6,8。为什么?
user2290820

3
i已经分配。next(a)表示将下一次迭代2分配给i,然后您a再次移动,打印i
。–马丁·彼得斯

1
如果n为奇数,则此方法不起作用- 在列表浏览后被调用StopIteration时,excpetio nis引发next(a)
拉夫

13

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

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

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

8

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

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

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

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

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


2

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

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

>>> 
0
2
4
6
8

像预期的那样工作。

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


5
我得到与@lvc相同的结果(但是仅在IDLE上,当以脚本执行时得到了此结果)
jamylak 2013年

3
@Inbar Rose仅当您作为脚本运行时。
Quintec

1
它是通过交互式外壳放置代码的行为。如果函数未使用返回值,则解释器会将其作为调试输出打印到外壳上
Reishin 18'Jan

2

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

>>> 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。将其返回值分配给变量不会神奇地改变其行为。


1

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

>>> def test():
...     a = iter(list(range(10)))
...     for i in a:
...         print(i)
...         next(a)
... 
>>> test()
0
2
4
6
8
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.