复制可迭代对象的Pythonic方法
我正在做一个小项目,需要遍历一个列表。对于这个循环中的每一个元素,我还需要再开始一个循环,这个新循环也是遍历同一个列表,但新循环的第一个元素是外层循环的当前元素。举个例子,我想实现的效果是这样的:
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 风格的代码。也许有人有其他的想法或者代码片段?我对“无法复制迭代器对象”这个问题产生了兴趣。有没有什么最佳实践可以在需要复制可迭代对象的情况下使用?还是说复制可迭代对象本身就是个愚蠢且没用的事情?
1 个回答
7
在想要复制一个可迭代对象时,有没有什么好的做法呢?
itertools.tee
可以给你两个迭代器,它们会输出和原始对象一样的内容,但它会把原始对象的所有输出都记住,所以你就不能再用原来的那个了。不过在这种情况下也没什么用,因为它会一直记住这些循环的值,直到你遇到内存错误。
或者说,复制可迭代对象一般来说是傻乎乎的和没用的?
迭代器的定义就是有一个当前状态,并且输出一个项目。你无法知道它们将来会输出哪些内容,或者过去输出过哪些内容。真正的复制需要同时做到这两点,所以这是不可能的!
在你的情况下,创建一个新的循环是非常简单的,我宁愿这样做,而不是试图复制一个已有的。例如:
def new_cycle( seq, last=None):
if last is None:
return cycle(seq)
else:
it = cycle(seq)
while next(it) != last:
pass
return it