Last modified: Mar 30, 2026 By Alexander Williams
Python Range vs Xrange: Key Differences
Python provides tools for creating sequences of numbers. Two important ones are range and xrange. They seem similar but work differently.
This article explains both functions. We will cover their syntax, behavior, and memory use. You will learn which one to use and when.
What is the Range Function?
The range function generates a list of numbers. It is a built-in Python function. You use it to create sequences for loops.
The basic syntax is range(stop). You can also use range(start, stop) or range(start, stop, step).
# Example of range()
my_range = range(5)
print(list(my_range))
# Output: [0, 1, 2, 3, 4]
In the example, range(5) creates numbers from 0 to 4. The list() function shows the sequence.
Range creates the entire list in memory at once. This is fine for small sequences. For large ones, it uses a lot of memory.
For a deeper look at its syntax, see our Python Range Function Guide.
What is the Xrange Function?
The xrange function also generates number sequences. It is available only in Python 2. It does not create a full list.
Instead, xrange returns an xrange object. This object yields numbers one by one as needed. This is called lazy evaluation.
# Example of xrange() in Python 2
# This code only works in Python 2
my_xrange = xrange(5)
print(my_xrange)
# xrange(5)
# To see values, iterate
for i in my_xrange:
print(i)
# Output from the for loop
0
1
2
3
4
The xrange object does not store all numbers. It calculates the next number when asked. This saves memory.
Key Differences: Range vs Xrange
The main difference is memory usage and return type.
Return Type:range returns a list. xrange returns an xrange object.
Memory:range uses more memory. It builds the complete list. xrange uses minimal memory. It generates values on the fly.
Performance: For large loops, xrange is faster to start. range has overhead to create the list first.
Operations: A list from range supports indexing and slicing. An xrange object is mainly for iteration.
# Comparing operations (Conceptual)
# Range allows indexing
r_list = range(0, 10, 2) # Creates [0, 2, 4, 6, 8]
print(r_list[2]) # Would output 4
# Xrange is not designed for indexing
# xr_obj = xrange(0, 10, 2)
# print(xr_obj[2]) # This might not work as expected in Python 2
Python 2 vs Python 3: A Major Shift
This is the most important point. Python 3 changed how these functions work.
In Python 3, the range function behaves like Python 2's xrange. It returns a range object, not a list. This object is memory-efficient.
The xrange function was removed in Python 3. If you try to use it, you will get a NameError.
# Python 3 behavior
new_range = range(5)
print(type(new_range))
print(list(new_range))
# Output in Python 3
<class 'range'>
[0, 1, 2, 3, 4]
In Python 3, you only need the range function. It gives you the best of both worlds: clean syntax and efficient memory use.
When to Use Range or Xrange?
Your choice depends on your Python version and needs.
For Python 3: Always use range. It is the only option and is efficient.
For Python 2: Use xrange in for-loops with large sequences. It saves memory. Use range when you need a real list for indexing or multiple uses.
If you are writing code for both versions, be careful. Consider using a compatibility check.
Practical Examples and Common Uses
Let's see some practical code. These examples work in Python 3. For Python 2, replace range with xrange for large numbers.
# Example 1: Basic for loop
print("Counting up:")
for number in range(3):
print(number)
# Example 2: With start and stop
print("\nFrom 2 to 6:")
for number in range(2, 7):
print(number)
# Example 3: With a step
print("\nEven numbers up to 10:")
for number in range(0, 11, 2):
print(number)
Counting up:
0
1
2
From 2 to 6:
2
3
4
5
6
Even numbers up to 10:
0
2
4
6
8
10
You can also create sequences in reverse. Learn how in our guide on Python Range Backwards.
A common question is about the stop value. Is it included? Read Is Python Range Inclusive? for the answer.
Memory Efficiency Demonstration
Let's compare memory use conceptually. This shows why the change in Python 3 is good.
# Python 2 style (Inefficient for large N)
# big_list = range(1000000) # Creates a list of 1 million integers in memory
# Python 2 style (Efficient)
# big_xrange = xrange(1000000) # Creates a small object
# Python 3 style (Efficient by default)
big_range = range(1000000) # Creates a small range object, not a list
print(big_range)
# Output in Python 3
range(0, 1000000)
The Python 3 range object is tiny. It only stores start, stop, and step values. It does not store all one million numbers.
Conclusion
The range and xrange story teaches a key Python lesson. It is about evolution and efficiency.
In Python 2, you had to choose. range gave a list. xrange gave efficiency. In Python 3, the range function became the efficient one.
Always use range in Python 3. If you maintain old Python 2 code, use xrange in loops for better performance.
Understanding this difference helps you write better, more memory-conscious code. It also helps you read older tutorials and adapt them to modern Python.
Remember, the range function is versatile. You can use it for forward, backward, and stepped sequences. It is a fundamental tool for every Python programmer.