在 Python 中使用 'for' 的无限循环

Infinite loops using 'for' in Python

为什么这不会产生无限循环?

a=5
for i in range(1,a):
  print(i)
  a=a+1

或这个

for i in range(1,4):
  print(i)
  i=i-1

或这个

for i in range(1,4):
  print(i)
  i=1

有没有什么方法可以使用 for 循环来创建无限循环?我知道有 while 循环,但我只是好奇。

考虑一个 for 循环:

for item in iterable:
    print(item)

想法是,只要 iterable 不变,我们将遍历 iterable 中的每个 item 一次。例如,

for item in [3, 2, 1, 666]:
    print(item)

会输出3 2 1 666。特别是,我们发现 range(1, 4) 是表示可迭代对象 [1, 2, 3] 的一种简单方法。因此,

for i in range(1, 4):
    print(i)

会输出1 2 3.


示例 1

a=5
for i in range(1,a):
  print(i)
  a=a+1

在这种情况下,range(1,a) 在循环开始时计算 一次

示例 2

for i in range(1,4):
  print(i)
  i=i-1

在这种情况下,在循环体内执行 printi=i-1 语句之前,每个循环都会重新评估 i

示例 3

for i in range(1,4):
  print(i)
  i=1

就像示例 2 一样,i 在每个循环中重新计算。

range is a class,并在其中使用,例如range(1, a) 创建 class 的 对象 。该对象仅创建 一次 ,它不会在循环的每次迭代中重新创建。这就是第一个示例不会导致无限循环的原因。

其他两个循环不是无限的,因为与 range 对象不同,循环变量 i 重新创建的(或者 重新初始化) 每次迭代。您在循环内分配给 i 的值将在循环迭代时被覆盖。

for 循环和 range(..) 对象

如果你写 for i in range(..): Python 而不是 将其翻译成类似 for(int i = 0; i < n; i++) 的东西(在 C 编程语言家族中)。

此外,范围对象在 for 循环之前构造一次。 range(..) 对象,不知道使用了哪些变量来构造它。构建后,范围为 fixed.

它将range(..)视为一个可迭代对象,并且每次迭代,它都采用可迭代产生的下一个项目。因此,无论您是否在 for 循环中设置变量,对下一次迭代都没有 影响。

中,range(..)不是具体的对象,而是构造列表的调用。所以如果你调用 range(10) (没有 for 循环),你会得到 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].

为什么不起作用?

那么为什么示例不起作用?

a=5
for i in range(1,a):
  print(i)
  a=a+1

这里我们构造一次range(..)。在那之后,构建它所基于的变量可以改变,因为 range(..) 对象不再改变了。因此,增加 a 并不意味着 range 对象会变大。

for i in range(1,4):
  print(i)
  i=i-1

for 循环每次获取可迭代对象的 next 项。因此,如果我们首先从 range 循环中收集了 1,那么在下一次迭代中,我们将收集 2。这与 i 的值是什么无关。

for i in range(1,4):
  print(i)
  i=1

出于同样的原因:for 没有 考虑 i 的先前值。它只获取可迭代的下一个项目(这里 range(..) 产生)。由于 range(..) 是固定的,它只会将下一个项目提供给 for 循环。

模拟无限循环

所以我们需要构造一个不断产生元素的迭代器。一种方法是 itertools.count:

from itertools import count

for i in count():
    # ...
    pass

或者如果您对任何值都不感兴趣,我们也可以使用 repeat

from itertools import repeat

for _ in repeat(None):
    # ...
    pass

因为范围是列表 (Python2) 或 range 对象,两者都是有限的。该范围在循环开始之前创建一次。您的循环变量在每次迭代开始时被分配范围的下一个元素,而不管您稍后在循环体中分配什么。您需要一个无限迭代器来进行无限循环,例如itertools.cycle:

from itertools import cycle
for x in cycle(range(5)):
    # endless

range 复制给它的参数供内部使用。因此,之后的更改无效。与循环变量相同,每次仅从内部值创建。

如果你使用像 list 这样的可变对象来迭代,那就不同了:

a = [1,2,3]

for i in a:
    a.append(i)

这个循环确实会运行无限。

在这种情况下,您不能更新 for 循环正在循环的迭代器。


for i in range(a): 中的 range 实际上是一个函数 - 它接受一个值 a 和 returns 一个包含它将循环遍历的值的对象。构建该对象后,您可以随心所欲地更改输入变量,并且该对象不会更改。

想象一下,如果我们创建自己的名为 my_range 的类似函数来生成一个列表(而内置的 range 函数生成一个 range):

def my_range(end):
    my_list = []
    for i in range(end):
        my_list.append(i)
    return my_list

现在如果我们要使用我们的新功能,就像这样:

a = 4
for i in my_range(a):
    print(i)
    a += 1

很明显,我们不能通过更改 a 来更新我们正在循环的列表对象,因为我们正在循环的列表已经创建,并且'不会在每个循环中重新制作。


你能在python中做一个无限循环吗?是的,只需向要循环访问的对象添加一个新条目,例如:

my_list = [0]
for i in my_list:
    print(i)
    my_list.append(i+1)

现在我们正在更新正在循环的对象。