[Python-Dev] copying of itertools iterators

Terry Reedy tjreedy at udel.edu
Fri Apr 2 01:52:43 CEST 2010


On 4/1/2010 7:20 PM, Andrew Svetlov wrote:
> using of copy.copy for simple iterators is forbidden
>
>>>> import copy
>>>> copy.copy(iter([1, 2, 3]))
> Traceback (most recent call last):
>    File "<stdin>", line 1, in<module>
>    File "/home/andrew/projects/py3k/Lib/copy.py", line 96, in copy
>      return _reconstruct(x, rv, 0)
>    File "/home/andrew/projects/py3k/Lib/copy.py", line 284, in _reconstruct
>      y = callable(*args)
>    File "/home/andrew/projects/py3k/Lib/copyreg.py", line 88, in __newobj__
>      return cls.__new__(cls, *args)
> TypeError: object.__new__(list_iterator) is not safe, use
> list_iterator.__new__()

The same happens for the iterators of other builtin classes: tuples, 
sets, and dicts (that I tried). In the other hand,
 >>> copy.copy(iter(range(1,3,1))) # 3.1
Traceback (most recent call last):
...
TypeError: rangeiter() requires 3 int arguments
and similar for filter and map.

I do not know whether the former group is detected by rule or explicit 
hard-coded list, but I suspect the latter.

> That behavior is safe and clean.
> But it's possible to copy iterator objects returned by itertools functions:
>
>>>> i = itertools.chain([1, 2], [3, 4, 5])
>>>> i.__next__()
> 1
>>>> j = copy.copy(i)

This works because itertools.chain() is legal

>>>> j.__next__()
> Traceback (most recent call last):
>    File "<stdin>", line 1, in<module>
> StopIteration

Because itertools.chain() is empty.

>>>> i.__next__()
> 2
>
> Looks like itertools object should be protected from usage like that.

I suspect only those for which itertools.xxx() works rather than raising 
an exception.

> Folks, what are you think about?

Why privilige the itertools module? A possible rule would be to not copy 
anything with both .__iter__ and .__next__.

Terry Jan Reedy



More information about the Python-Dev mailing list