Python Range Data Type
Introduction
After carefully exploring collection data types such as list, tuple, set, frozen set, and even the mapping-based structure dictionary, it becomes important to understand that not all data structures are meant to store arbitrary collections of values; some are specifically designed to represent structured, predictable sequences, especially when the data follows a numeric pattern. One such highly useful and frequently used data type in Python is the range, which is designed to efficiently represent a sequence of numbers without explicitly storing all of them in memory.
In real-world programming, it is extremely common to work with sequences such as numbers from 0 to 9, or from 1 to 100, or even more complex progressions, and instead of manually creating such sequences using lists, Python provides a more optimized and elegant way through the range data type, which allows us to define these sequences declaratively.
What is Range?
A range in Python represents a sequence of numbers, and it is primarily used when you want to generate numbers in a predictable pattern, such as consecutive integers or numbers with a fixed step difference.
Instead of storing all values explicitly, a range object internally keeps track of:
- The starting value
- The ending boundary
- The step (increment or decrement)
and generates values only when required, making it highly efficient in terms of memory usage.
Creating a Range Object
The simplest way to create a range is by using the built-in range() function.
r = range(10)
When a single argument is provided:
- It represents numbers from 0 to n-1
- In this case: 0 to 9
print(type(r)) # <class 'range'>
Why Range Does Not Print Values Directly
If you try print(r), you will not see the actual numbers; instead, Python displays something like:
range(0, 10)
This happens because range is not a list but a sequence object, and to access individual values, we need to iterate over it.
Accessing Values Using Loop
for x in r:
print(x) # 0 1 2 3 4 5 6 7 8 9
This confirms that the range represents values from 0 to 9.
Three Forms of Range
Python provides three different ways to create a range object, and understanding each form deeply is essential.
Form 1: range(n)
r = range(10)
This form generates values from 0 to n-1. So:
- range(10) → 0 to 9
- range(100) → 0 to 99
Form 2: range(begin, end)
r = range(1, 10)
This generates values from begin to end - 1.
So:
- range(1, 10) → 1 to 9
Form 3: range(begin, end, step)
This is the most powerful form.
r = range(1, 21, 2)
This generates:
- Starting from 1
- Incrementing by 2
- Until less than 21
Output is 1, 3, 5, 7, 9, 11, ....
Understanding Step Value
The third argument defines how values progress.
Increment by 1 (default)
range(1, 21, 1) # 1, 2, 3, 4, ..., 20
Using Negative Step (Decrement)
Range also supports reverse sequences.
r = range(20, 0, -5) # 20, 15, 10, 5
This demonstrates that range can move backward as well.
Order in Range
Since range represents a sequence, order is always preserved, and this is a crucial property. Because order exists:
- Indexing is possible
- Slicing is possible
Indexing in Range
r = range(10, 21)
print(r[0]) # 10
print(r[-1]) # 20
Slicing in Range
r = range(10, 21)
r1 = r[1:5]
for x in r1:
print(x) # 11 12 13 14
This shows that slicing produces a new range-like sequence.
Important Property: Range is Immutable
One of the most critical properties of range is that it is immutable, meaning once it is created, its values cannot be modified.
r = range(10, 21)
r[1] = 100 # Not allowed
Output:
TypeError: 'range' object does not support item assignment
This happens because range represents a mathematical sequence, and modifying individual values would break its internal consistency.
Why Range is Immutable
If you think logically, a range represents a pattern such as:
10, 11, 12, 13, ...
If you try to replace one value arbitrarily, the sequence loses its meaning, and therefore Python prevents such modifications.