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
)。参见 。
首先,我知道我应该使用 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
)。参见