为什么循环会像这样(与 tee 结合使用)?

Why does a loop behave like this, (in conjunction with 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 循环的行为以及为什么以这种方式更改生成器会导致它提前退出。)

来自 documentation:

Once tee() has made a split, the original iterable should not be used anywhere else; otherwise, the iterable could get advanced without the tee objects being informed.

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

This itertool may require significant auxiliary storage (depending on how much temporary data needs to be stored). In general, if one iterator uses most or all of the data before another iterator starts, it is faster to use list() instead of 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?