为什么循环表现得像这样(与tee结合)?

时间:2017-05-01 15:36:40

标签: python itertools tee

我正在尝试迭代一对组合。

虽然从概念和实用的角度来看,我已经想出了一个更好的方法,这是我的第一个冲动,我想知道它为什么不起作用。

gen = itertools.combinations(range(1, 6), 3)
for i in gen:
  gen, gencopy = itertools.tee(gen)
  for j in gencopy:
    print(i, j)

提供以下输出:

  

(1,2,3)(1,2,4)
  (1,2,3)(1,2,5)
  (1,2,3)(1,3,4)
  (1,2,3)(1,3,5)
  (1,2,3)(1,4,5)
  (1,2,3)(2,3,4)
  (1,2,3)(2,3,5)
  (1,2,3)(2,4,5)
  (1,2,3)(3,4,5)

这意味着只会迭代i中的一个。

但是,如果我将tee行更改为:

_, gencopy = itertools.tee(gen)

我得到了一整套预期的对。

(注意:我已经发现执行此操作的最佳方法是简单地将生成器反馈到itertools.combinations以恢复组合对,并避免文档声称与tee一起出现的性能问题但是,我很好奇for循环的行为以及为什么以这种方式更改生成器会导致它提前保释。)

1 个答案:

答案 0 :(得分:1)

来自documentation

  

一旦tee()进行了拆分,原始的iteable不应该在其他任何地方使用;否则,迭代可以在不通知tee对象的情况下进行。

在输出中使用多于1个迭代器时tee的想法是在迭代器之间共享对象(每个对象都“消耗”原始列表)。

  

此itertool可能需要大量辅助存储(取决于需要存储多少临时数据)。通常,如果一个迭代器在另一个迭代器启动之前使用大部分或全部数据,则使用list()而不是tee()会更快。

在你的情况下恰好发生了什么:内部循环消耗所有数据,外部循环立即退出。

文档建议的解决方法:

gen = list(itertools.combinations(range(1, 6), 3))
for i in gen:
  for j in gen:
    print(i, j)

但当然这可能会占用大量内存,因为您从一开始就“杀死”了生成器功能。所以你使用组合而不是双循环的想法可能是最好的。

相关的问与答:How to clone a Python generator object?