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

我知道有很多不同的方法可以实现我想要的,但我正在寻找一些简短、清晰和 python 的代码。也许有人有另一个想法,甚至是一个片段?无法复制迭代器对象这一事实引起了我的兴趣。在需要可迭代副本的情况下是否有最佳实践?还是一般来说复制迭代是愚蠢和无用的?

4

1 回答 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
于 2010-09-30T00:12:08.710 回答