【问题标题】:How to store itertools.chain and use it more than once?如何存储 itertools.chain 并多次使用它?
【发布时间】:2012-10-20 19:50:50
【问题描述】:

我想使用itertools.chain 来高效连接列表(记忆),但我需要能够多次读取(或map 等)结果。这个例子说明了这个问题:

import itertools
a = itertools.chain([1, 2], [3, 4])
print list(a) # => [1, 2, 3, 4]
print list(a) # => []

避免这个问题的最佳方法是什么?

【问题讨论】:

    标签: python memoization itertools


    【解决方案1】:

    与所有生成器一样,您需要将其转换为列表并存储该结果:

    a = list(a)
    

    这是生成器的基本原理,它们被期望只生成一次序列一次。

    此外,您不能简单地存储生成器用于记忆目的,因为基础列表可能会更改。在几乎所有的记忆用例中,您应该存储列表;生成器通常只是一种有效转换或过滤底层序列的方法,并不代表您要记忆的数据本身。就好像你在存储一个函数,而不是它的输出。在您的特定情况下,如果您所做的只是使用 chain() 连接现有列表,请直接存储这些列表。

    请注意,这使生成器能够生成无限序列,因此在转换为列表时要小心。

    【讨论】:

    • 感谢您的信息。听起来我应该只连接列表。有没有比list1 + list2 + ... 更有效的方法?
    • @jtbandes:您可以使用timeit 来比较list(chain()) 和list1 + ..,但我怀疑后者将是最有效的。
    【解决方案2】:

    试试itertools.tee:

    import itertools
    a = itertools.chain([1, 2], [3, 4])
    a, b = itertools.tee(a)
    print list(b) # => [1, 2, 3, 4]
    a, b = itertools.tee(a)
    print list(b) # => [1, 2, 3, 4]
    

    【讨论】:

    • 这并不能改变记忆生成器毫无用处的事实,真的。
    • 来自文档:通常,如果一个迭代器在另一个迭代器启动之前使用了大部分或全部数据,则使用 list() 而不是 tee() 会更快。
    • @PaoloMoretti:请注意,发帖人并没有问什么更快或更好,他们的问题是如何重用生成器,而 itertools.tee 正是提供了这一点。
    • @thg435 我的评论更多的是给可能遇到这个问题的其他人的注意
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 2013-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多