Search code examples
pythoniteratorxrange

why is xrange able to go back to beginning in Python?


I've encountered this code from Most pythonic way of counting matching elements in something iterable

r = xrange(1, 10)
print sum(1 for v in r if v % 2 == 0) # 4
print sum(1 for v in r if v % 3 == 0) # 3

r is iterated once. and then it's iterated again. I thought if an iterator is once consumed then it's over and it should not be iterated again.

Generator expressions can be iterated only once:

r = (7 * i for i in xrange(1, 10))
print sum(1 for v in r if v % 2 == 0) # 4
print sum(1 for v in r if v % 3 == 0) # 0

enumerate(L) too:

r = enumerate(mylist)

and file object too:

f = open(myfilename, 'r')

Why does xrange behave differently?


Solution

  • Because the xrange object produced by calling xrange() specifies an __iter__ that provides a unique version of itself (actually, a separate rangeiterator object) each time it's iterated.

    >>> x = xrange(3)
    >>> type(x)
    <type 'xrange'>
    >>> i = x.__iter__()
    >>> type(i)
    <type 'rangeiterator'>