I noticed some weird behaviour when I copy.copy
an itertools.chain
:
from copy import copy
from itertools import chain
When I exhaust one of them the result is as expected:
>>> a = chain([1,2,3], [4,5,6])
>>> b = copy(a)
>>> list(a), list(b)
([1, 2, 3, 4, 5, 6], [])
>>> a, b = chain_and_copy()
>>> list(b), list(a)
([1, 2, 3, 4, 5, 6], [])
However when I use next
the results seem odd:
>>> a = chain([1,2,3], [4,5,6])
>>> b = copy(a)
>>> next(a), list(b), list(a)
(1, [4, 5, 6], [2, 3]) # b "jumps" to the second iterable...
>>> a = chain([1,2,3], [4,5,6])
>>> next(a)
1
>>> b = copy(a)
>>> next(a), next(b), next(a)
(2, 3, 4)
>>> next(b) # b is empty
StopIteration:
>>> next(a) # a is not empty
5
Is that a Bug or is shallow copying an iterator generally a bad idea? I noticed that a copy of iter
and a copy of zip
behave differently too:
>>> a = zip([1,2,3], [4,5,6])
>>> b = copy(a)
>>> next(a), next(b)
((1, 4), (2, 5)) # copies share the same "position"
>>> a = iter([1,2,3])
>>> b = copy(a)
>>> next(a), next(b)
(1, 1) # copies don't share the same "position"