无限迭代器是否有表达式?

158 投票
7 回答
97142 浏览
提问于 2025-04-16 16:08

有没有一种简单的方法可以创建一个无限的迭代器呢?

这个问题纯粹是理论上的,不需要什么“实际”的答案哦 :)


比如,使用生成器表达式可以很容易地创建一个有限的迭代器:

my_gen = (0 for i in range(42))

但是,要创建一个无限的迭代器,我就需要在我的命名空间里添加一个虚假的函数,这样就有点麻烦了:

def _my_gen():
    while True:
        yield 0
my_gen = _my_gen()

把这些放在一个单独的文件里,然后再import进来是不算的。


我也知道itertools.repeat正好可以做到这一点。我很好奇有没有一种一行代码就能解决这个问题的方法,而不需要用到这个。

7 个回答

27

你可以循环遍历一个可调用的对象,这个对象返回的常量总是和iter()的哨兵值不同。

g1 = iter(lambda: 0, 1)
290

itertools 提供了三种无限循环的迭代器:

  • count(start=0, step=1): 这个会从0开始,依次输出 0, 1, 2, 3, 4, ... 一直往下数。

  • cycle(p): 这个会循环遍历你给的列表,比如 p[0], p[1], ..., p[-1], 然后又回到 p[0], ... 一直重复。

  • repeat(x, times=∞): 这个会一直输出你给的值 x,比如 x, x, x, x, ... 一直重复下去。

我不知道标准库里还有其他的。


既然你要一个简短的例子:

__import__("itertools").count()
174
  • 两个参数的 iter = 一个不带参数的可调用对象 + 哨兵值
  • int() 总是返回 0
for x in iter(int, 1): pass

所以,iter(int, 1) 是一个无限迭代器。显然,这种用法有很多变种(特别是当你加入 lambda 的时候)。其中一个特别值得注意的变种是 iter(f, object()),因为使用新创建的对象作为哨兵值几乎可以保证无论第一个参数用什么可调用对象,都会得到一个无限迭代器。

撰写回答