イテレータのコピー
イテレータはコピーできない。
>>> import copy >>> def it(): ... for i in xrange(10): ... yield i ... >>> list(it()) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> a = it() >>> b = copy.copy(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Python26\lib\copy.py", line 95, in copy return _reconstruct(x, rv, 0) File "C:\Python26\lib\copy.py", line 323, in _reconstruct y = callable(*args) File "C:\Python26\lib\copy_reg.py", line 93, in __newobj__ return cls.__new__(cls, *args) TypeError: object.__new__(generator) is not safe, use generator.__new__()
代わりにitertools.teeを使う。
>>> import itertools >>> a = it() >>> b = itertools.tee(a) >>> a, b = itertools.tee(a) >>> list(a) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list(a) [] >>> list(b) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
ちなみに、xrangeはコピーできる。
xrangeはイテレータではないから。
>>> a = xrange(10) >>> b = copy.copy(a) >>> a xrange(10) >>> b xrange(10) >>> a.next() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'xrange' object has no attribute 'next'
xrangeをfor文を使わずイテレータとして利用するなら、
しかし、当然コピーは出来なくなる。
>>> a = xrange(10) >>> iter(a) <rangeiterator object at 0x009EC530> >>> ait = iter(a) >>> ait.next() 0 >>> copy.copy(ait) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Python26\lib\copy.py", line 95, in copy return _reconstruct(x, rv, 0) File "C:\Python26\lib\copy.py", line 323, in _reconstruct y = callable(*args) File "C:\Python26\lib\copy_reg.py", line 93, in __newobj__ return cls.__new__(cls, *args) TypeError: object.__new__(rangeiterator) is not safe, use rangeiterator.__new__()