Search code examples
pythonrangexrange

xrange as an iterator and chunking


The snippets

 xi = xrange(10)
 zip(xi,xi)

and

 xi = iter(range(10))
 zip(xi,xi)

behave differently. I expected to get

  [(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]

in the first snippet as well, but it returns

[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9)]

instead. It seems the implicit container is being silently copied. Could anyone explain whats going on here ? and reasoning behind choosing such semantics.

>>> sys.version
'2.7.9 (default, Dec 10 2014, 12:28:03) [MSC v.1500 64 bit (AMD64)]'

Solution

  • An xrange is not any sort of iterator. People keep calling it a generator, but it's not; an xrange is an immutable sequence, like a tuple:

    >>> x = xrange(5)
    >>> x[2]
    2
    >>> for i in x:
    ...     print i
    ...
    0
    1
    2
    3
    4
    >>> for i in x:
    ...     print i
    ...
    0
    1
    2
    3
    4
    

    As with any other sequence type, each time you request an iterator from an xrange, you get a new, independent iterator. Thus, when you zip xrange(10) with itself, you get the same output as if you had zipped [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] with itself, rather than if you had zipped iter([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) with itself.