Python 中的无限循环 - 列表是否已更新?

Infinite for loop in Python - is the list updated or not?

首先,我知道我应该使用 while 循环来创建一个无限循环。然而,在 Python 中制作无限 for 循环时,我 运行 进入了我不完全理解的东西。

我对 "infinite" for 循环的想法如下:

l = [1]
for el in l:
  print(len(l))
  l.append(1)

这实际上创建了一个无限循环,因为 1 在每次循环迭代中不断附加到列表 l 中。所以我想我不希望我的列表变得越来越长,以至于在某些时候我没有足够的内存。所以我这样做了:

l = [1]
for el in l:
  print(len(l))
  l.pop(0)
  l.append(1)

我只得到了一次迭代。有人可以解释为什么吗?是因为 l 仍然引用同一个对象并且它的长度总是 1 吗?

如果您按照上面的建议使用 iterator,实施起来会更容易。
下面的 class 实现了迭代器 classes

所需的 ___iter______next___ 方法
class WhileLoop:

    def __init__(self, value):
        #Assign the value
        self.value = value

    def __iter__(self):
        #The iterator will be the class itself
        return self

    def __next__(self):
        #The next element in the loop is the value itself
        return self.value

然后您可以按如下方式调用并循环此迭代器。

loop = WhileLoop(1)
for item in loop:
    print(item)

for statement return 是一个 "iterator" 的容器,它是数据流的容器,return 一次是一个元素,因此您不会迭代在可迭代对象(在本例中为您的列表)上,而不是在这个容器上。

您可以 return 直接使用 iter() 这个迭代器,以便更好地理解您的 for 循环发生了什么。

items = ['a']

it = iter(items)
print(it.__reduce__())
# (<built-in function iter>, (['a'],), 0)

内置__reduce__()函数return关于迭代器的状态信息。请注意,在创建迭代器后立即编辑的状态信息 return 包括可迭代对象 ['a'] 和索引值 0。索引值指示将由迭代器 return 编辑的下一个元素的位置。

为了模拟循环的第一次迭代,我们可以使用 next(),其中 return 是迭代器的下一个元素。

next(it)
print(it.__reduce__())
# (<built-in function iter>, (['a'],), 1)

现在我们看到索引值已更改为 1,因为迭代器已经 return 编辑了列表中的第一个元素,并且在下一次迭代中它将尝试 return列表中的第二个元素。如果您尝试删除列表中的第一个元素,然后将另一个元素添加到列表中,则以下是迭代器的结果状态。

items.pop(0)
items.append('b')
print(it.__reduce__())
# (<built-in function iter>, (['b'],), 1)

您可以看到删除了第一个元素并附加了新元素(如预期的那样)。但是,迭代器仍然保留索引值 1 作为要从迭代中 returned 的下一个元素的位置。如果我们尝试另一次迭代,将引发 StopIteration 异常,因为在我们的迭代器容器使用的可迭代对象中索引 1 处没有元素。

next(it)
# Traceback (most recent call last):
#   File "main.py", line 16, in <module>
#     next(it)
# StopIteration

如果您真的对创建无限循环感兴趣,使用生成器将是解决内存问题的更好方法(尽管正如您在问题中指出的那样,没有太多充分的理由不这样做对这种事情使用 while)。参见