复制可迭代对象的Pythonic方法

6

我正在做一个小项目,需要循环遍历一个列表。对于这个循环中的每个元素,我都要从同样的列表中开始另一个循环,以前一个元素作为新循环的第一个元素。例如,我想要能够产生类似下面的东西:

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的代码。也许有人有另一个想法,甚至有一小段代码?事实上,不可能复制迭代器对象引起了我的兴趣。在想要复制可迭代对象的情况下,是否存在最佳实践?或者复制可迭代对象总是愚蠢和无用的?


1
他们并不傻,PEP 323 考虑了可复制迭代器的问题。 - Matt
1个回答

7
在想要复制可迭代对象时,是否有最佳实践?
使用 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接