Pythonic复制可迭代对象的方法

时间:2010-09-29 23:58:24

标签: python copy cycle itertools

对于我正在研究的小项目,我需要在列表中循环。对于这个循环的每个元素,我必须通过相同的列表开始另一个循环,前一个元素作为新循环的第一个元素。例如,我希望能够产生这样的东西:

1, 2, 3, 4, 1, 2, 3, 4, 1, ...
2, 3, 4, 1, 2, 3, 4, 1, 2, ...
3, 4, 1, 2, 3, 4, 1, 2, 3, ...
4, 1, 2, 3, 4, 1, 2, 3, 4, ...
1, 2, 3, 4, 1, 2, 3, 4, 1, ...
...

我认为在每个.next()之后复制一个itertools.cycle会保留当前状态,这样我就可以使用“外部”循环中的元素开始新的循环。甚至“将循环指针”重置为较旧的位置。我尝试了以下方法:

>>> import itertools, copy
>>> a = itertools.cycle([1, 2, 3, 4])
>>> b = copy.copy(a)

但得到了这个错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/copy.py", line 95, in copy
    return _reconstruct(x, rv, 0)
  File "/usr/lib/python2.6/copy.py", line 323, in _reconstruct
    y = callable(*args)
  File "/usr/lib/python2.6/copy_reg.py", line 93, in __newobj__
    return cls.__new__(cls, *args)
TypeError: cycle expected 1 arguments, got 0

我知道有很多不同的方法来实现我想要的东西,但我正在寻找一些简短,清晰和pythonic的代码。也许有人有另一个想法甚至是一个片段?事实是not possible to copy iterator objects唤醒了我的兴趣。在需要可复制副本的情况下,是否存在最佳实践?或者一般来说,复制迭代是愚蠢无用的吗?

1 个答案:

答案 0 :(得分:5)

  

在情况下是否有最好的做法   谁想要一个可迭代的副本?

itertools.tee为您提供了两个迭代器,每个迭代器都会生成与原始项目相同的项目,但它会获取原始内容并记住它产生的所有内容,因此您无法再使用原始内容。但这并没有帮助,因为它会记住这些循环值,直到你得到一个MemoryError。

  

或者正在复制迭代的傻瓜   一般没用?

迭代器只是定义为具有当前状态并产生项目。您无法判断他们将来是否会产生相同的物品,或者他们过去会产生哪些物品。真正的副本必须要做到这两点,所以这是不可能的!

在你的情况下,制作一个新的循环是非常微不足道的,我宁愿这样做而不是尝试复制现有的循环。例如:

def new_cycle( seq, last=None):
    if last is None:
        return cycle(seq)
    else:
        it = cycle(seq)
        while next(it) != last:
            pass
        return it