Python 2: range vs xrange
In Python 2, there were two functions:
range()— Created a list in memoryxrange()— Created an iterator (lazy evaluation, memory efficient)
Python 2: range()
# Python 2 only:
r = range(1000000) # Creates a list with 1 million numbers in memory
print(type(r)) #
This used a lot of memory for large ranges.
Python 2: xrange()
# Python 2 only:
x = xrange(1000000) # Creates an iterator, doesn't store all numbers
print(type(x)) # <type 'xrange'>
# Only generates numbers when you iterate:
for i in x:
print(i) # Numbers generated one at a time
This was memory efficient, generating numbers on demand.
Python 3: range() only
In Python 3, xrange() was removed, and range() now works like the old xrange():
# Python 3:
r = range(1000000) # Creates a range object (like old xrange)
print(type(r)) #
# Memory efficient:
print(r[0]) # 0 (can still index)
print(r[999]) # 999
print(len(r)) # 1000000
# But doesn't store all numbers in memory
for i in r:
print(i) # Numbers generated on demand
What changed
| Python 2 | Python 3 |
|---|---|
range() — creates list |
range() — creates range object (memory efficient) |
xrange() — creates iterator |
xrange() — removed (doesn't exist) |
Today (Python 3)
Just use range() — it's always memory efficient:
# All of these work the same way (memory efficient):
for i in range(10):
print(i)
for i in range(0, 10):
print(i)
for i in range(0, 10, 2): # Step by 2
print(i)
# Can convert to list if needed:
numbers = list(range(10)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Benefits of Python 3 range()
- Memory efficient: Doesn't create a list, generates numbers on demand
- Still indexable: Can use
range(10)[5]to get5 - Supports slicing:
range(10)[2:5]works - Has length:
len(range(10))returns10
If you need a list
If you specifically need a list (not just iteration), convert it:
# Create a list from range:
my_list = list(range(10)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# Or use list comprehension:
my_list = [i for i in range(10)] # Same result
Summary
- Python 2: Use
xrange()for memory efficiency,range()if you need a list - Python 3: Just use
range()— it's always memory efficient - If migrating: Replace
xrange()withrange()in Python 3 code