In Python 2:
range(n)eagerly built a list of integers (memory heavy for largen).xrange(n)returned an xrange object that generated values lazily.
In Python 3:
range(n)returns a lazyrangeobject (immutable sequence) that computes values on demand.- There is no
xrange; Py3rangecovers that role. - You can index, slice, and take
len(), but it is not a list. Uselist(range(...))if you need a real list.
# Python 3 r = range(1_000_000) print(type(r)) # <class 'range'> print(len(r)) # 1000000 print(r[10]) # 10 print(r[:3]) # range(0, 3) print(list(r[:3])) # [0, 1, 2] # Memory: range object is tiny vs equivalent list import sys print(sys.getsizeof(range(1_000_000))) print(sys.getsizeof(list(range(1_000)))) # already much larger for smaller n
Migration note: Code that depended on range returning a list in Py2 must wrap with list(...) under Py3 if mutation/list methods are required.