why is xrange able to go back to beginning in Python?
Question: I've encountered this code from [Most pythonic way of counting matching
elements in something
iterable](http://stackoverflow.com/questions/157039/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?


Answer: Because `xrange` does not return a generator. It returns an [xrange
object](http://docs.python.org/library/functions.html#xrange).

    
    
    >>> type(xrange(10))
    <type 'xrange'>
    

In addition to repeated iteration, `xrange` objects support other things that
generators don't -- like indexing:

    
    
    >>> xrange(10)[5]
    5
    

They also have a length:

    
    
    >>> len(xrange(10))
    10
    

And they can be reversed:

    
    
    >>> list(reversed(xrange(10)))
    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    

In short, `xrange` objects implement the full
[sequence](http://docs.python.org/glossary.html#term-sequence)
[interface](http://docs.python.org/library/collections.html#collections-
abstract-base-classes):

    
    
    >>> import collections
    >>> isinstance(xrange(10), collections.Sequence)
    True
    

They just do it without using up a lot of memory.

Note also that in Python 3, the `range` object returned by `range` has all the
same properties.

