In Python 2, [range](<https://docs.python.org/2/library/functions.html#range>) function returns a list while [xrange](<https://docs.python.org/2/library/functions.html#xrange>) creates a special xrange object, which is an immutable sequence, which unlike other built-in sequence types, doesn’t support slicing and has neither index nor count methods:

print(range(1, 10))
# Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]

print(isinstance(range(1, 10), list))
# Out: True

print(xrange(1, 10))
# Out: xrange(1, 10)

print(isinstance(xrange(1, 10), xrange))
# Out: True

In Python 3, xrange was expanded to the [range](<https://docs.python.org/3/library/functions.html#func-range>) sequence, which thus now creates a range object. There is no xrange type:

print(range(1, 10))
# Out: range(1, 10)

print(isinstance(range(1, 10), range))
# Out: True

# print(xrange(1, 10))
# The output will be:
#Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#NameError: name 'xrange' is not defined

Additionally, since Python 3.2, range also supports slicing, index and count:

print(range(1, 10)[3:7])
# Out: range(3, 7)
print(range(1, 10).count(5))
# Out: 1
print(range(1, 10).index(7))
# Out: 6

The advantage of using a special sequence type instead of a list is that the interpreter does not have to allocate memory for a list and populate it:

# range(10000000000000000)
# The output would be:
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# MemoryError

print(xrange(100000000000000000))
# Out: xrange(100000000000000000)

Since the latter behaviour is generally desired, the former was removed in Python 3. If you still want to have a list in Python 3, you can simply use the list() constructor on a range object:

print(list(range(1, 10)))
# Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]

Compatibility

In order to maintain compatibility between both Python 2.x and Python 3.x versions, you can use the [builtins](<http://python-future.org/compatible_idioms.html#xrange>) module from the external package [future](<http://python-future.org/>) to achieve both forward-compatiblity and backward-compatiblity:

# forward-compatible
from builtins import range

for i in range(10**8):
    pass
# backward-compatible
from past.builtins import xrange

for i in xrange(10**8):
    pass

The range in future library supports slicing, index and count in all Python versions, just like the built-in method on Python 3.2+.