【问题标题】:Python list iterator behavior and next(iterator)Python 列表迭代器行为和 next(iterator)
【发布时间】:2013-05-24 18:40:26
【问题描述】:

考虑:

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

它没有。循环打印列表中的 all 项,而不跳过任何项。

我的第一个想法是这可能会发生,因为循环调用 iter 对其传递的内容,这可能会给出一个独立的迭代器 - 情况并非如此,因为我们有 iter(a) is a

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

【问题讨论】:

    标签: python list iterator iteration


    【解决方案1】:

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

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

    按预期工作。

    在 Python 2.7 和 Python 3+ 中测试。在两者中都能正常工作

    【讨论】:

    • 我得到与@lvc 相同的结果(但仅在 IDLE 上,当作为脚本执行时我得到这个))
    • @Inbar Rose 仅​​当您作为脚本运行时。
    • 这是通过交互式外壳放置代码的行为。如果函数没有使用就返回值,解释器会将其打印到 shell 作为调试输出
    【解决方案2】:

    您看到的是 interpreter 除了在每次迭代中打印 i 之外,还回显了 next() 的返回值:

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

    所以0print(i) 的输出,1next() 的返回值,由交互式解释器回显,等等。只有 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() 正在按预期工作,但由于它从迭代器返回下一个值,并由交互式解释器回显,因此您会相信循环具有自己的迭代器副本。

    【讨论】:

    • 我不知道解释器的这种行为。我很高兴在解决一些实际问题时浪费大量时间思考它之前发现了这一点。
    • ... *死了*。最糟糕的是,我记得大概在一周前向某人确切地提到了这种解释器行为。
    • 有趣。我在 a 中尝试了 for i: next(a) ;print i 并认为我会跳到 1 并打印 1、3、5、7、9。但它仍然是 0,2,4,6,8。为什么?
    • i分配。 next(a) 表示下一次迭代2 被分配给i,然后你再次移动a,打印i,等等。
    • 如果 n 是奇数,这将不起作用 - 在列表耗尽后调用 next(a) 时会引发 StopIteration 异常。
    【解决方案3】:

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

    你可以做的是用这个值影响一个变量:

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

    【讨论】:

      【解决方案4】:

      我发现现有的答案有点令人困惑,因为它们只是间接表明代码示例中的基本神秘事物:both* “print i”和“next(a)”导致他们的结果将被打印出来。

      由于它们正在打印原始序列的交替元素,并且“next(a)”语句正在打印是出乎意料的,因此“print i”语句似乎正在打印所有值。

      鉴于此,将“next(a)”的结果分配给变量会禁止打印其结果,因此只会打印“i”循环变量的替代值,这一点变得更加清楚。同样,让“print”语句发出更独特的东西也可以消除歧义。

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

      一般来说,回答问题最吸引人的地方在于,一旦你知道了答案,你就会清楚地表明什么是显而易见的。它可能难以捉摸。同样,一旦你理解了答案,就会批评它们。很有意思……

      【讨论】:

        【解决方案5】:

        如果作为函数调用,它会按照你想要的方式运行:

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

        【讨论】:

          【解决方案6】:

          对于那些仍然不明白的人。

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

          【讨论】:

            猜你喜欢
            • 2012-10-11
            • 2016-04-21
            • 2015-05-20
            • 2022-06-16
            • 2017-09-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-08-16
            相关资源
            最近更新 更多