tags:

views:

1746

answers:

11

Apparently xrange is faster but I have no idea why it's faster (and no proof besides the anecdotal so far that it is faster) or what besides that is different about

for i in range(0, 20):
for i in xrange(0, 20):
+2  A: 

see here.

Oko
+4  A: 

xrange returns an iterator and only keeps one number in memory at a time. range keeps the entire list of numbers in memory.

Ben Hoffstein
+29  A: 

range creates a list, so if you do range(1, 10000000) it creates a list in memory with 10000000 elements.

xrange is a generator, so it evaluates lazily.

Charles
+2  A: 

range generates the entire list and returns it. xrange does not -- it generates the numbers in the list on demand.

Eddie Deyo
+1  A: 

xrange uses an iterator (generates values on the fly), range returns a list.

hacama
+3  A: 

Do spend some time with the Library Reference. The more familiar you are with it, the faster you can find answers to questions like this. Especially important are the first few chapters about builtin objects and types.

The advantage of the xrange type is that an xrange object will always take the same amount of memory, no matter the size of the range it represents. There are no consistent performance advantages.

Another way to find quick information about a Python construct is the docstring and the help-function:

print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
Antti Rasinen
The library is good but it's not always so easy to get the answer to the question you have.
Teifion
Go to the library reference, hit ctrl+f, search for range and you will get two results. It's not much effort to find the answer to this question.
David Locke
+2  A: 

It is for optimization reasons.

range() will create a list of values from start to end (0 .. 20 in your example). This will become an expensive operation on very large ranges.

xrange() on the other hand is much more optimised. it will only compute the next value when needed (via an xrange sequence object) and does not create a list of all values like range() does.

QAZ
+16  A: 

range creates a list, so if you do range(1, 10000000) it creates a list in memory with 10000000 elements. xrange is a generator, so it evaluates lazily.

This is true, but in Python 3, range will be replaced with xrange(). If you need to actually generate the list, you will need to do:

list(range(1,100))
Corey
I don't see that being a huge problem (regarding breaking existing applications) as range was mostly for generating indexes to be used in for loops as "for i in range(1, 10):"
toast
+5  A: 

xrange only stores the range params and generates the numbers on demand. However the C implementation of Python currently restricts its args to C longs:

xrange(2**32-1, 2**32+1)  # OverflowError: cannot convert to int
range(2**32-1, 2**32+1)   # OK --> [4294967295L, 4294967296L]

Note that in Python 3.0 there is only range and it behaves exactly like the 2.x xrange.

efotinis
+2  A: 

range creates a list, so if you do range(1, 10000000) it creates a list in memory with 10000000 elements. xrange is a generator, so it evaluates lazily.

This brings you two advantages:

  1. You can iterate longer lists without getting a stackoverflow error.
  2. As it resolves each number lazily, if you skip the iteration early, you wont have the penalization of the creation of the whole list.
Lucas S.
+2  A: 

Remember, use the timeit module to test which of small snipps of code is faster!

$ python -m timeit 'for i in range(1000000):' ' pass'
10 loops, best of 3: 90.5 msec per loop
$ python -m timeit 'for i in xrange(1000000):' ' pass'
10 loops, best of 3: 51.1 msec per loop

Personally, I always use range(), unless I were dealing with really huge lists -- as you can see, time-wise, for a list of a million entries, the extra overhead is only 0.04 seconds. And as Corey points out, in Python 3.0 xrange will go away and range will give you nice iterator behaviour anyway.

John Fouhy