Python / range() / Create Consecutive or Evenly Spaced Integers

Python’s range() creates an immutable sequence representing evenly spaced integers. It includes the starting value but excludes the stop boundary; the sign of step chooses increasing or decreasing order. It differs from a list storing all values and from a generator consumed as you iterate.

Basic rules for start, stop, and step

The range reference describes range(stop), range(start, stop), and range(start, stop, step). Omitted start is zero and omitted step is one. Arguments must be integers or support the integer-index protocol; ordinary floats and numeric strings are not converted automatically.

Use Python 3. Save each complete example in UTF-8 as range_example.py and run python range_example.py, or python3 where appropriate. Replace the contents for independent runs. For small ranges, list() displays all values.

print(list(range(4)))
print(list(range(1, 6)))
print(list(range(1, 10, 2)))

Expected output:

[0, 1, 2, 3]
[1, 2, 3, 4, 5]
[1, 3, 5, 7, 9]

range(4) gives zero through three; range(1, 6) gives one through five. To include five in an increasing unit-step range, set stop to six. With step two, the last value need not be stop minus one: it must satisfy both spacing and the boundary.

Negative steps and empty ranges

Positive steps include values smaller than stop; negative steps include values greater than stop. Descending requires a negative step. If the direction does not fit the boundaries, the result is an empty range rather than an error.

print(list(range(10, -5, -3)))
print(list(range(5, 0, -1)))
print(list(range(5, 0)))
print(list(range(0, 5, -1)))
print(list(range(3, 3)))
[10, 7, 4, 1, -2]
[5, 4, 3, 2, 1]
[]
[]
[]

range(10, -5, -3) produces 10, 7, 4, 1, -2. The next value, -5, equals stop and is excluded. Use range(5, 0, -1) for five down to one. Equal start and stop also produce an empty range, whose loop body never executes.

Index and iterate without a list

Printing a range displays its representation rather than every element. It calculates values from its bounds and step, supporting length, indexing, slicing, and membership tests. Because it is immutable, you cannot replace an element by assigning to its index.

numbers = range(2, 10, 2)
print(numbers)
print(len(numbers))
print(numbers[0], numbers[-1])
print(list(numbers[1:3]))
print(6 in numbers, 7 in numbers)
print(list(numbers))
print(list(numbers))
range(2, 10, 2)
4
2 8
[4, 6]
True False
[2, 4, 6, 8]
[2, 4, 6, 8]

Converting the same range to a list twice gives the same elements. The range itself is not an exhaustible generator. A separate iterator created with iter(numbers) is consumed, so distinguish the sequence from its iterator. Slicing returns another range; the example converts it to a list for inspection.

Zero steps, floats, and strings raise errors

Step zero cannot define progression and raises ValueError. 3.0 remains a float despite its integral value, while "3" is a string; both raise TypeError.

for arguments in ((1, 5, 0), (3.0,), ("3",)):
    try:
        print(range(*arguments))
    except (ValueError, TypeError) as error:
        print(type(error).__name__)
ValueError
TypeError
TypeError

If integer text is an accepted input, validate it and convert with int() separately. Blindly truncating floats may produce an unintended range, so define the input policy first. The exception handling here compares three invalid inputs; it is not a pattern for silently treating failed work as successful.

Choose range or enumerate for your loop

A range loop suits a fixed count or integer steps. Iterate over a list directly when you only need its elements. For elements with numbers, enumerate() avoids manual index calculations.

for number in range(1, 4):
    print("Step", number)

names = ["Ada", "Bo"]
for number, name in enumerate(names, start=1):
    print(number, name)
Step 1
Step 2
Step 3
1 Ada
2 Bo

The first loop has three steps, numbered one through three. In the second, start=1 changes numbering without skipping the first list item. range(len(items)) remains useful when actual indices or index-based position calculations are required.

Distinguish huge ranges from feasible work

A range can represent large boundaries without storing the whole integer list, but it does not eliminate the time needed to visit every value. In CPython, len()’s length representation limit can cause OverflowError even when the range itself can be created.

import sys

numbers = range(sys.maxsize + 1)
print(numbers[0])
print(numbers[-1] == sys.maxsize)
try:
    print(len(numbers))
except OverflowError:
    print("OverflowError")
0
True
OverflowError

This example checks only endpoints and the length error; it does not traverse the sequence. sys.maxsize varies by environment. Avoid casually materializing huge ranges with list(); iterate over only the needed portion or process results incrementally.