【发布时间】:2013-11-03 16:57:06
【问题描述】:
我正在使用iter(range()),但我还需要使用两次结果,假设j=iter(range(n,2n))
next(j) 将是 n,但我需要再次确定 next(j) 而不向前走,这可能没有进一步的复杂性吗?
【问题讨论】:
标签: python python-3.x iterator
我正在使用iter(range()),但我还需要使用两次结果,假设j=iter(range(n,2n))
next(j) 将是 n,但我需要再次确定 next(j) 而不向前走,这可能没有进一步的复杂性吗?
【问题讨论】:
标签: python python-3.x iterator
您可以轻松编写一个生成器,将给定迭代器的每个元素重复两次:
def repeat_iter(iter, n = 2):
for x in iter:
for i in range(n):
yield x
for x in repeat_iter(range(n)):
print x
如果您的用例需要向前看,请参阅this question 了解一些不错的解决方案。
【讨论】:
一种方法是显式获取两个迭代器,使用itertools.tee:
iter1,iter2 = itertools.tee(iter(range(5,10)))
next(iter1)
Out[15]: 5
next(iter2)
Out[16]: 5
这可能更灵活,具体取决于您在做什么,但缺点是您需要确保从两个迭代器中进行一对一的消费。
但老实说,我认为我从未发现自己使用range 这样做过。当您将next() 分配给一个变量时,您可以根据需要多次访问它(a la for i in range),所以...
【讨论】:
或者你可以使用生成器语句
for i in (j for j in range(n, 2 * n) for k in range(2)):
pass
【讨论】:
你可以使用zip:
for a, b in zip(range(...), range(...)):
...
【讨论】:
我相信shx2's answer 是问题的正确答案。
但是,如果
那么这里有一个不同的生成器,它可以通过 send() builtin 对反馈做出反应。
def iter_with_standstill(iter):
standstill = False
for x in iter:
while True:
pause = yield x
if pause is not None:
standstill = pause
yield None
if not standstill:
break
使用的技巧是任何generator.send(value) 的调用都会将value 作为yield 的结果接收它的生成器发送回。由于任何send() 都会导致生成器也立即运行到下一个yield(),我们yield(None) 在这里立即将控制权交还给调用代码。这种方法使send()真正实现了单向操作。
使用方法如下:
orig = range(10)
paused = iter_with_standstill(orig)
waiting = None
for x in paused:
if x in [4,7]:
if waiting is None:
waiting = 3
waiting -= 1
if waiting > 0:
paused.send(True)
else:
paused.send(False)
waiting = None
print(x, end=' ')
print()
waiting 变量的全部意义在于在值 4 和 7 处暂停,并重新迭代这些值最多 3 次。输出如下:
0 1 2 3 4 4 4 5 6 7 7 7 8 9
【讨论】: