2 回答
TA贡献1850条经验 获得超11个赞
结合评论中的建议,您可以实现您正在寻找的确切行为。我不会详细介绍生成器的工作原理,因为有经验的人会给出更简洁的答案。我总结一下,生成器的要点是,它们仅在您要求时才yield为您提供下一个元素。生成器与 Python 中的其他任何对象一样都是对象,因此只要您共享同一个生成器对象,您将始终拥有最后一个元素ed的书签。现在通过代码更好地理解:yield
首先我们来概括一下这个looper函数:
def looper(iterable, runs):
i = cycle(iterable)
for _ in range(runs):
print(next(i))
return i
runs所以现在它允许您在任何可迭代对象上调用一次函数,次数不限。另一方面,如果您打算多次调用它,它将返回创建的生成器以供重用。
现在我们来测试一些案例:
a = [1, 2, 3]
looper(a, 6)
这将打印:
1
2
3
1
2
3
但更重要的是,这还将:
i = looper(a, 2)
looper(i, 2)
looper(i, 2)
笔记:
我们之所以能够做到这一切,是因为itertools.cycle返回了一个生成器对象。
如果您希望在调用之间产生循环效果,则必须将返回的生成器传递给后续调用。例如,如果我们尝试这样做looper(a, 2)几次,我们总是会得到:
1
2
这是因为每次我们调用该函数时,我们都会再次调用并从从第一个元素开始的原始列表中cycle创建一个新的生成器。
另一方面,当将生成器传递给函数时,该cycle函数将创建一个新的生成器,但从前一个生成器停止的位置开始。这样,如果您继续传递第一个返回的cycle生成器,您将保留循环效果。
TA贡献1775条经验 获得超11个赞
您在这里提出两个问题。符合您的问题标题的第一个是如何(打印)列表的循环内容(您在此处使用“looper”),而不是破坏代码中提供的大量运行的代码。
我测试了您的代码,实际上,例如,runs = 13,您的代码中断并出现错误代码 IndexError:列表索引超出范围。
我看到你对更好的算法的要求更多,所以我使用 python 下限除法运算符(//)作为循环(或频率),并使用 python 提醒除法(%)作为提醒。
正如我们在数学上所知,5//2 = 2 和 5%2 = 1
这里的算法是通过计算的周期相应地打印所有列表内容,然后打印剩余的提醒。注意python默认索引是从0开始的。
这是我建议的代码
def looper(lst, runs):
cycle = (runs-1)//len(lst)
reminder = (runs-1)%len(lst)
print('cycle', cycle)
print('reminder', reminder)
for i in range(cycle):
for j in lst:
print(j)
for index, k in enumerate(lst):
if index <= reminder:
print(k)
# runs must be any positive integer
runs = 13
looper(['A', 'B', 'C'], runs)
我已经用 running = 13 对其进行了测试,代码不会中断打印以下内容,如预期的那样
周期 4 提醒 0 A B C A B C A B C A B C A
第二个问题(或要求)是每当这段代码运行时,起始索引不是从0开始,而是从最后一个提醒开始(我们可以将其视为指针),我认为这是另一个主题。但我也可能会回到这里给出这个解决方案。干杯。
添加回答
举报