【问题标题】:Pythonic way of copying an iterable object复制可迭代对象的 Pythonic 方式
【发布时间】:2011-04-19 02:40:12
【问题描述】:

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

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 的代码。也许有人有其他想法甚至是sn-p?它是not possible to copy iterator objects 的事实引起了我的兴趣。在需要可迭代副本的情况下是否有最佳实践?还是一般来说复制迭代是愚蠢和无用的?

【问题讨论】:

  • 他们并不傻,PEP 323 考虑过制作可复制的迭代器。

标签: python copy cycle itertools


【解决方案1】:

在某些情况下是否有最佳实践 哪里想要一个可迭代的副本?

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-18
    • 2018-08-19
    • 2010-11-21
    • 2018-06-10
    • 2017-03-05
    • 1970-01-01
    • 1970-01-01
    • 2018-11-28
    相关资源
    最近更新 更多