Python的itertools.cycle()文档给出了伪代码实现:
def cycle(iterable):
# cycle('ABCD') --> A B C D A B C D A B C D ...
saved = []
for element in iterable:
yield element
saved.append(element)
while saved:
for element in saved:
yield element
下面,它说:“注意,这个工具包的成员可能需要大量的辅助存储(取决于可迭代的长度)。”
我基本上是沿着这条路走下去了,除了我做了这个,这不需要创建一个可迭代的副本:
def loop(iterable):
it = iterable.__iter__()
while True:
try:
yield it.next()
except StopIteration:
it = iterable.__iter__()
yield it.next()
x = {1, 2, 3}
hard_limit = 6
for i in loop(x):
if hard_limit <= 0:
break
print i
hard_limit -= 1
打印:
1
2
3
1
2
3
是的,我意识到我的实现不适用于str,但可以实现。我更好奇为什么它会创建另一个副本。我有一种感觉它与垃圾收集有关,但我在Python的这个领域没有得到很好的研究。
谢谢!
答案 0 :(得分:14)
Iterables只能通过迭代。
您可以在循环中创建 new iterable。循环不能这样做,它必须与你传入的任何东西一起工作。cycle
不能简单地重新创建迭代。因此,它被迫存储原始迭代器产生的所有元素。
如果您传入以下生成器,则loop()
会失败:
def finite_generator(source=[3, 2, 1]):
while source:
yield source.pop()
现在你的loop()
产生了:
>>> hard_limit = 6
>>> for i in loop(finite_generator()):
... if hard_limit <= 0:
... break
... print i
... hard_limit -= 1
...
1
2
3
您的代码仅适用于序列,使用cycle()
会过多;在这种情况下,您不需要cycle()
的存储负担。简化为:
def loop_sequence(seq):
while True:
for elem in seq:
yield elem