next() 是否从生成器中删除值?

Does next() eliminate values from a generator?

我写了一个生成器,它只存储 0 到 10 的范围:

result = (num for num in range(11))

当我想打印值时,我可以使用next():

print(next(result))
[Out]: 0
print(next(result))
[Out]: 1
print(next(result))
[Out]: 2
print(next(result))
[Out]: 3
print(next(result))
[Out]: 4

如果我然后 运行 生成器上的 for 循环,它 运行 是我没有调用 next() 的值:

for value in result:
    print(value)
[Out]: 5
6
7
8
9
10

生成器是否通过使用 next() 函数作用于其他值来消除它们?我试图找到一些关于 next() 和生成器功能的文档,但没有成功。

实际上这可以从 nextdocs and by understanding the iterator protocol/contract:

中隐含地推导出来

next(iterator[, default])
Retrieve the next item from the iterator by calling its next() method. If default is given, it is returned if the iterator is exhausted, otherwise StopIteration is raised.

。使用生成器的 __next__ 方法检索 并从生成器中删除 下一个值。

tldr;是的

迭代器本质上是一个价值生产者,它从其关联的可迭代对象中产生连续的值。内置函数 next() 用于从迭代器中获取下一个值。 这是一个使用与上面相同列表的示例:

>>> l = ['Sarah', 'Roark']
>>> itr = iter(l)
>>> itr
<list_iterator object at 0x100ba8950>
>>> next(itr)
'Sarah'
>>> next(itr)
'Roark'
>>> next(itr)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

在此示例中,l 是一个可迭代列表,itr 是关联的迭代器,通过 iter() 获得。每个 next(itr) 调用从 itr.

获取下一个值

注意迭代器如何在内部保留其状态。它知道已经获得了哪些值,所以当你调用 next() 时,它知道接下来要 return 的值。

如果迭代器中的所有值都已经 returned,后续的 next() 调用会引发 StopIteration 异常。任何进一步从迭代器获取值的尝试都将失败。

我们只能从一个方向的迭代器中获取值。我们不能倒退。没有 prev() 函数。但是我们可以在同一个可迭代对象上定义两个独立的迭代器:

>>> l
['Sarah', 'Roark', 30]
>>> itr1 = iter(l)
>>> itr2 = iter(l)
>>> next(itr1)
'Sarah'
>>> next(itr1)
'Roark'
>>> next(itr1)
30
>>> next(itr2)
'Sarah'

是的,Python 中的 for 循环只是 returns 迭代器的下一个项目,与 next() 的方式相同。

https://docs.python.org/3/reference/compound_stmts.html#the-for-statement

The suite is then executed once for each item provided by the iterator, in the order returned by the iterator.

所以你可以这样想一个for循环:

for x in container:
    statement()

(几乎)相当于一个 while 循环:

iterator = iter(container)
while True:
    x = next(iterator)
    if x is None:
        break
    statement()

如果container已经是一个迭代器,那么iter(container)就是container

注意:从技术上讲,for循环更像是这样:

iterator = iter(container)
while True:
    try:
        x = iterator.__next__()
    except StopIteration:
        break
    statement()