I see that they produce the same result, is the difference in speed? Why are there 2 functions for the same thing?
> 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
Yes,
range
andxrange
they produce the same result but in a different way.The bases
As you may have already guessed, the function
range
returns a list:The range function will occupy the amount of memory according to the size of the range that you pass to it as a parameter.
On the other hand, the function
xrange
returns its own data type, the xrange-type :Well, there is not much science behind the
xrange
, in fact it does not have any differencerange
in terms of performance, the advantage is thatxrange
it will always occupy the same amount of memory (RAM) regardless of the size of the range:In short, the ultimate goal of both functions is to return lists, but we could say that
xrange
they do so on demand due to their "lazy" nature.Iterators
In both cases there is support for the iteration protocol since both have the method
__iter__
:So the following cases are equivalent:
The same applies to
xr
. The big difference is that when you iterate overr
you are doing it over a list that has already been evaluated (and loaded into memory) and when iterating overxr
you are doing it over a "lazy" list that passes you the values 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 original question but it seemed pertinent to add it to the answer since generators are objects that finally implement the iteration protocol.
They are similar to list comprehensions but are created using parentheses instead of square brackets.
Examples:
Now, the generators work in a similar way
xrange
as they are also "lazy" and only return the value as long as you need it without loading everything into memory by using the expressionyield
.References
The function
range
generates an internal temporary list that is manipulated item by item, whilexrange
producing an interator (defines the interface to walk through the aggregate of items and access them, so that the client doesn't have to know the details and is able to handle them anyway) which can be passed through without the expense of what could be a large temporary list object.Example:
Stop
x
atrange(10000)
: It will generate a list of 10 thousand elements and then it will go through each one of them in turn.For
x
inxrange(10000)
: Will generate 10 thousand integers one by one, passing each one to the variable x in turn.Reference
In python2, they are different functions and their minor differences are explained quite well in the xrange documentation : it
xrange
generates an xrange object , and itrange
generates a list. The advantage of the objectXRange
is that it does not need to generate all the elements until it is necessary, which means significant resource savings. In addition, in the CPython implementation (which is the most common of python) this type of loops can be optimized much better and simpler.With Python3 there are no longer two functions, unifying into a single function
range
that would be equivalent to thexrange
python2 function. To get a list it is necessary to call the list constructor (eg:list(range(1000))
)