如何使用 itertools 生成无限序列
How to generate infinite sequence with itertools
我想生成两个 0 和 1 的不定式序列,具体顺序如下:
0、1、0、-1、0、1、0、-1、...
我创建了以下代码,除了:
return 什么都没有
# for in loop
for i in itertools.cycle(range(0,2)):
if i == 0:
i += 1
if i == 1:
i -= 1
if i == 0:
i -= 1
print(i, end = " ")
只是 return 一系列 -1。无法弄清楚错误在哪里。谁能给点建议
您可以使用 itertools.cycle()
的方式明确说明您要生成的元素:
from itertools import cycle
cycle([0, 1, 0, -1])
作为替代方案,您可以使用一些简单的模块化算法实现自己的生成器:
def seq():
i = 0
while True:
yield (-1)**(i // 2) * (i % 2)
i = (i + 1) % 4 # keeps i small, so as not to take up too much memory
演示:
>>> s = seq()
>>> [next(s) for _ in range(10)]
[0, 1, 0, -1, 0, 1, 0, -1, 0, 1]
我知道 OP 声明他们特别想使用 itertools,但这可能对其他人仍然有帮助。
正如评论中指出的那样,您还可以通过传递任意参数并使用 yield from
来简单地模拟 itertools.cycle
(请注意,itertools.cycle
实际上在幕后的工作方式不同):
def seq(*args):
while True:
yield from args
s = seq(0, 1, 0, -1)
但在我看来,这不如算出实际的算术序列有趣:D
不确定您为什么坚持在这样的 for
循环中使用 itertools.cycle
,但有一种方法可以实现此目的:
for i in itertools.cycle(range(0, 2)):
if i == 0:
print(i, end=" ")
i += 1
print(i, end=" ")
i -= 1
print(i, end=" ")
i -= 1
print(i, end=" ")
请注意,使用嵌套的 if
语句确实没有意义,因为每个嵌套的谓词将始终为真:如果 i
为零,然后向其加一,则 当然你的嵌套谓词if i == 1
会是真的...
此外,您在 for
循环中使用 itertools.cycle
是 anti-pattern。如 BrokenBenchmark 的回答所示,您可以简单地循环遍历序列本身的元素,永远。如果您坚持使用for
循环:
for i in itertools.cycle([0, 1, 0, -1]):
print(i, end=" ")
虽然这种方法有很多问题。也就是说,正如我在评论中讨论的那样,这是一个无限 loop 与无限 [= 根本不同的行为36=]序列。有了无限循环,就再也不会发生任何其他事情了——您的程序将永远在您的四个元素上循环,而无法做任何其他事情。
如果您按原意使用 itertools.cycle
-- 作为生成器 -- 您可以随时从序列中中断的地方继续,这样您就可以执行其他任务在继续序列之前如你所愿:
c = itertools.cycle((0, 1, 0, -1))
next(c) # 0
next(c) # 1
next(c) # 0
next(c) # -1
# do something else for a while
next(c) # 0
# yield the next 10 items from the sequence
for _ in range(10):
print(next(c), end=" ")
# do something else again
我想生成两个 0 和 1 的不定式序列,具体顺序如下:
0、1、0、-1、0、1、0、-1、...
我创建了以下代码,除了:
return 什么都没有# for in loop
for i in itertools.cycle(range(0,2)):
if i == 0:
i += 1
if i == 1:
i -= 1
if i == 0:
i -= 1
print(i, end = " ")
只是 return 一系列 -1。无法弄清楚错误在哪里。谁能给点建议
您可以使用 itertools.cycle()
的方式明确说明您要生成的元素:
from itertools import cycle
cycle([0, 1, 0, -1])
作为替代方案,您可以使用一些简单的模块化算法实现自己的生成器:
def seq():
i = 0
while True:
yield (-1)**(i // 2) * (i % 2)
i = (i + 1) % 4 # keeps i small, so as not to take up too much memory
演示:
>>> s = seq()
>>> [next(s) for _ in range(10)]
[0, 1, 0, -1, 0, 1, 0, -1, 0, 1]
我知道 OP 声明他们特别想使用 itertools,但这可能对其他人仍然有帮助。
正如评论中指出的那样,您还可以通过传递任意参数并使用 yield from
来简单地模拟 itertools.cycle
(请注意,itertools.cycle
实际上在幕后的工作方式不同):
def seq(*args):
while True:
yield from args
s = seq(0, 1, 0, -1)
但在我看来,这不如算出实际的算术序列有趣:D
不确定您为什么坚持在这样的 for
循环中使用 itertools.cycle
,但有一种方法可以实现此目的:
for i in itertools.cycle(range(0, 2)):
if i == 0:
print(i, end=" ")
i += 1
print(i, end=" ")
i -= 1
print(i, end=" ")
i -= 1
print(i, end=" ")
请注意,使用嵌套的 if
语句确实没有意义,因为每个嵌套的谓词将始终为真:如果 i
为零,然后向其加一,则 当然你的嵌套谓词if i == 1
会是真的...
此外,您在 for
循环中使用 itertools.cycle
是 anti-pattern。如 BrokenBenchmark 的回答所示,您可以简单地循环遍历序列本身的元素,永远。如果您坚持使用for
循环:
for i in itertools.cycle([0, 1, 0, -1]):
print(i, end=" ")
虽然这种方法有很多问题。也就是说,正如我在评论中讨论的那样,这是一个无限 loop 与无限 [= 根本不同的行为36=]序列。有了无限循环,就再也不会发生任何其他事情了——您的程序将永远在您的四个元素上循环,而无法做任何其他事情。
如果您按原意使用 itertools.cycle
-- 作为生成器 -- 您可以随时从序列中中断的地方继续,这样您就可以执行其他任务在继续序列之前如你所愿:
c = itertools.cycle((0, 1, 0, -1))
next(c) # 0
next(c) # 1
next(c) # 0
next(c) # -1
# do something else for a while
next(c) # 0
# yield the next 10 items from the sequence
for _ in range(10):
print(next(c), end=" ")
# do something else again