【问题标题】:Why does a loop behave like this, (in conjunction with tee)?为什么循环的行为是这样的,(与 tee 一起使用)?
【发布时间】:2017-09-29 00:39:43
【问题描述】:

我正在尝试迭代成对的组合。

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

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)

这意味着只有一个 is 被迭代。

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

_, gencopy = itertools.tee(gen)

我得到了完整的预期对。

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

【问题讨论】:

  • python 3.4:无论哪种方式,我都得到相同的输出:你发布的那个。
  • 来自文档“一旦 tee() 进行了拆分,原始的可迭代对象不应在其他任何地方使用;否则,可迭代对象可以在不通知 tee 对象的情况下前进。”。因此,无论哪种方式,您的代码都不正确。
  • 奇怪,我使用的是 Python 3.6.0

标签: python itertools tee


【解决方案1】:

来自documentation

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

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

此迭代工具可能需要大量辅助存储(取决于需要存储多少临时数据)。一般来说,如果一个迭代器在另一个迭代器启动之前使用了大部分或全部数据,那么使用 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?

【讨论】:

    猜你喜欢
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 2016-05-26
    • 1970-01-01
    • 2021-08-16
    相关资源
    最近更新 更多