What is the difference between range and xrange in python?

I see that they produce the same result, is the difference in speed? Why are there 2 functions for the same ?

> range(5)
[0, 1, 2, 3, 4]
>>> xrange(5)
xrange(5)
>>> for i in range(5):
...     print i
... 
0
1
2
3
4
>>> for i in xrange(5):
...     print i 
... 
0
1
2
3
4
 15
Author: ChemaCortes, 2016-02-21

3 answers

Yes, range and xrange they produce the same result but in different ways.

The bases

As you have already guessed the function range returns a list:

>>> type(range(10))
list

The range function will occupy the amount of memory according to the size of the range you pass as a parameter.

On the other hand the function xrange returns its own data type, the xrange-type :

>>> type(xrange(10))
xrange

For there is not much science behind the xrange, in fact it has no difference from range in terms of performance, the advantage is that xrange will always occupy the same amount of memory (RAM) no matter the size of the range:

The xrange type is an immutable sequence which is commonly used for looping. 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.

In short, the ultimate goal of both functions is to return lists but we could say that xrange does so on demand because of its "lazy" or "lazy"nature.

Iterators

In both cases there is support for the iteration protocol since both have the method __iter__:

>>> r = range(10)
>>> r
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> r.__iter__
<method-wrapper '__iter__' of list object at 0xb603fdcc>

>>> xr = xrange(10)
>>> xr
xrange(10)
>>> xr.__iter__
<method-wrapper '__iter__' of xrange object at 0xb600e4d0>

So the following cases are equivalent:

>>> for item in r:
...     print item
...
0
1
2
3
4
5
6
7
8
9
>>> for item in r.__iter__():
...     print item
...
0
1
2
3
4
5
6
7
8
9

The same alpica for xr. The big difference is that when iterating on r you are doing it on a list that has already been previously evaluated (and loaded into memory) and by iterating on xr you are doing it on a "loose" list that is passing the values to you as long as you need them (loading into memory one at a time).

Now this may not make much sense with a range of 10 integers, but try it with a few million and you'll notice the difference in your RAM.

Generators

I know this is not part of the initial question but I found it pertinent to add it to the answer since generators are objects that ultimately implement the iteration protocol.

Are similar to comprehension lists but are created using parentheses instead of brackets.

Examples:

>>> lista = [1, 2, 3, 4, 5]
>>> [x**2 for x in lista]
[1, 4, 9, 16, 25]
>>> (x**2 for x in lista)
<generator object <genexpr> at 0xb60427fc>

Now, generators work similarly to xrange since they are also "loose" and only return the value as long as you need it without loading everything into memory by using the expression yield.

References

 18
Author: César, 2016-03-10 12:01:10

Function range generates a list of temporary internal that is manipulated, article by article, while xrange produces an interator (defines the interface to iterate through the addition of elements and access them, so that the client does not have to know the details and be able to deal with them anyway) through which you can pass without the expense of what could be an object of list big storm.

Example:

For x in range(10000): It will generate a list of 10 thousand elements and then it will go through each of them at once.

For x in xrange(10000): It will generate 10 thousand integers one by one, passing each to the variable x at a time.

Reference

 9
Author: Max Sandoval, 2016-02-24 17:11:20

In python2, they are different functions and it is explained quite well in the documentation of xrange their minimal differences: xrangegenerates a xrange object, and range generates a list. The advantage of the XRange object is that it is not necessary to generate all the elements as long as it is not needed, which is a significant saving of resources. In addition, in the implementation CPython (which is the most common python) you can optimize much better and simple this type of loop.

With Python3 there are no longer two functions unifying into a single function range which would be equivalent to the function xrange of python2. To get a list you need to invoke the list constructor (eg: list(range(1000)))

 6
Author: ChemaCortes, 2016-02-21 17:34:47