How to use range() in Python
Learn how to use Python's range() function with examples, tips, real-world applications, and common error fixes. Master looping in Python.

The Python range() function creates number sequences, a fundamental task for loops and iterations. It provides a simple method to control program flow and handle repetitive tasks with efficiency.
Here, you'll explore core techniques, practical tips, and real-world applications for the range() function. You'll also find debugging advice to help you implement it effectively in your projects.
Basic usage of range()
for i in range(5):
print(i, end=' ')--OUTPUT--0 1 2 3 4
The simplest use of range() involves a single argument, which defines the sequence's upper limit. In the example, range(5) creates an iterable object that produces numbers from 0 up to—but not including—5. This is the default behavior:
- The sequence starts at 0.
- It increments by 1.
- It stops before reaching the specified number.
This makes it a clean and Pythonic way to execute a loop a specific number of times without manually initializing or incrementing a counter variable. For a broader understanding of different looping in Python approaches, you can explore various loop types and their use cases.
Alternative ways to use range()
While its basic form is powerful, the range() function offers even more control by letting you define custom start, stop, and step parameters for your sequences.
Using range() with start, stop, and step parameters
for i in range(2, 10, 2):
print(i, end=' ')--OUTPUT--2 4 6 8
The range() function becomes even more flexible when you use all three of its possible arguments. In range(2, 10, 2), you're telling Python to start counting at 2 and to stop before it reaches 10. The final argument, 2, sets the step, creating a sequence that increases by two with each iteration.
start: The first number in the sequence.stop: The sequence ends just before this number.step: The difference between each number in the sequence.
Using range() with negative step
for i in range(10, 0, -1):
print(i, end=' ')--OUTPUT--10 9 8 7 6 5 4 3 2 1
The range() function can also count backward. To do this, you just need to provide a negative step value and ensure your start value is greater than your stop value.
- In
range(10, 0, -1), the sequence begins at 10. - It decrements by 1 with each step.
- The loop stops just before reaching 0, making the final number 1.
This creates a simple countdown, which is perfect for reversing iterations or processing data in reverse order.
Converting range() to other data types
numbers_list = list(range(1, 6))
numbers_tuple = tuple(range(1, 6))
numbers_set = set(range(1, 6))
print(numbers_list, numbers_tuple, numbers_set)--OUTPUT--[1, 2, 3, 4, 5] (1, 2, 3, 4, 5) {1, 2, 3, 4, 5}
The range() function generates numbers on demand, but it doesn't store them all in memory at once. To work with the full sequence as a collection, you can convert the range object into other data types like lists, tuples, or sets. This approach is particularly useful when creating a list of numbers for further processing.
- Wrapping
range()inlist()creates a mutable list like[1, 2, 3, 4, 5]. - Using
tuple()creates an immutable tuple:(1, 2, 3, 4, 5). - Passing it to
set()produces a set of unique elements:{1, 2, 3, 4, 5}.
This is useful when you need to store, modify, or perform collection-specific operations on the numbers.
Advanced techniques with range()
Building on its core functionality, range() can be combined with other Python tools to create more concise, readable, and memory-friendly code.
Using range() in list comprehensions
squares = [x**2 for x in range(1, 6)]
print(squares)
cubes = [x**3 for x in range(1, 6)]
print(cubes)--OUTPUT--[1, 4, 9, 16, 25]
[1, 8, 27, 64, 125]
List comprehensions offer a compact syntax for creating lists. When paired with range(), you can generate a sequence and apply an operation in one line. For example, [x**2 for x in range(1, 6)] builds a list by squaring each number from 1 to 5, perfect for rapid prototyping and vibe coding.
- This approach is often more readable and efficient than using a traditional
forloop to append items to a list. - The expression—like
x**2orx**3—is placed at the beginning, making the intent clear.
Using range() with enumerate()
fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits, start=1):
print(f"Fruit {index}: {fruit}")--OUTPUT--Fruit 1: apple
Fruit 2: banana
Fruit 3: cherry
When you need to loop over a list and also know the position of each item, enumerate() is the ideal tool. It’s a more Pythonic alternative to using range(len(fruits)), as it gives you both the index and the value in each iteration without extra work.
enumerate()pairs each item from an iterable, like a list, with a counter.- The optional
startparameter, as instart=1, lets you begin counting from any number instead of the default 0.
This approach makes your code cleaner and more readable, especially when you need numbered lists or formatted output.
Memory efficiency of range()
large_range = range(1, 1000000)
size_in_bytes = large_range.__sizeof__()
print(f"Size: {size_in_bytes} bytes")
print(f"First: {large_range[0]}, Last: {large_range[-1]}")--OUTPUT--Size: 48 bytes
First: 1, Last: 999999
One of the biggest advantages of range() is its memory efficiency. Unlike a list, a range object doesn't store every number in the sequence. It only holds the start, stop, and step values, calculating each number as needed. This is why range(1, 1000000) consumes very little memory regardless of its massive size.
- Numbers are generated on the fly during iteration, which keeps memory usage low.
- You can still access elements by index, like
large_range[-1], because the object computes the value instantly upon request.
Move faster with Replit
Replit is an AI-powered development platform that comes with all Python dependencies pre-installed, so you can skip setup and start coding instantly. Instead of just piecing together techniques like range(), you can use Agent 4 to build the complete application you have in mind.
Describe what you want to build, and Agent will take it from an idea to a working product. Here are a few examples:
- A data sampling tool that pulls every tenth entry from a list for quick analysis.
- A log formatter that adds a unique, sequential ID to every line item for better tracking.
- A task scheduler that generates a list of dates for recurring weekly or bi-weekly events.
Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.
Common errors and challenges
While range() is straightforward, a few common mistakes can trip you up, especially when you're just getting started with Python.
Forgetting that range() is exclusive of the end value
A frequent mistake is expecting range(5) to include the number 5. Remember, the stop parameter is an upper boundary that the sequence never reaches, which can cause loops to run one less time than intended. To include a specific number, you must set the stop value to one higher, as in range(6).
Using non-integer arguments with range()
The range() function is strict about its arguments—they must all be integers. Trying to use a float, like range(2.5, 10.0), will result in a TypeError because the function is designed for discrete, countable steps. If you need to work with floating-point numbers, you'll have to use a different approach, such as a while loop.
Off-by-one errors when using range() with indices
Off-by-one errors are a classic programming challenge that often appears when using range() to access list items by index. For example, using range(len(my_list)) correctly generates indices from 0 up to the final item. However, a small mistake like using range(1, len(my_list)) will cause your loop to skip the first element entirely. An even more common error is trying to access an index that doesn't exist, which results in an IndexError.
Forgetting that range() is exclusive of the end value
It's a classic off-by-one error. You might expect range(1, 10) to produce numbers from 1 to 10, but it stops at 9. This happens because the stop value is an endpoint, not an included number. See what this looks like below.
for i in range(1, 10):
print(i, end=' ')
This code prints numbers from 1 up to 9, which can be a problem if your goal was to include 10. The fix is a simple change to the stop argument. See how it's done in the example below.
for i in range(1, 11):
print(i, end=' ')
By changing the stop argument to 11, the loop now correctly includes the number 10. The range(1, 11) function generates numbers starting from 1 and stops just before reaching 11, making 10 the final value. This simple adjustment is crucial when your logic depends on including a specific endpoint. Always double-check your stop value to prevent off-by-one errors in your loops.
Using non-integer arguments with range()
The range() function is strict about its inputs. It only works with whole numbers, so trying to use a float like 5.5 won't work. This will stop your code with a TypeError. See what happens when you try it below.
for i in range(0, 5.5):
print(i, end=' ')
This code triggers a TypeError because range() doesn't accept floats like 5.5; it only understands integer steps. The next example shows a common workaround for handling sequences with floating-point numbers.
for i in range(0, int(5.5)):
print(i, end=' ')
The solution is to explicitly convert the float to an integer using the int() function. This works because int() truncates the decimal portion, so int(5.5) evaluates to 5. The range() function can then correctly generate a sequence from 0 up to 4.
This technique is especially handy when your loop's boundary comes from a calculation or user input that might produce a float. It ensures your code remains robust without crashing.
Off-by-one errors when using range() with indices
Using range() to loop through list indices can easily lead to an off-by-one error. If your range is even one number short, you'll accidentally skip the last item in your list, which can silently break your program's logic.
The code below shows how this common mistake looks in practice.
items = ["apple", "banana", "cherry", "date", "elderberry"]
for i in range(len(items) - 1):
print(items[i])
By subtracting one with len(items) - 1, the range becomes too short. Since range() already excludes the endpoint, the loop stops at the second-to-last index, completely missing the final element. Check out the corrected code below.
items = ["apple", "banana", "cherry", "date", "elderberry"]
for i in range(len(items)):
print(items[i])
The correct approach is to pass len(items) directly to range(). Because range() stops before its endpoint, using the list's full length automatically generates the correct sequence of indices from 0 to the final item. This simple adjustment guarantees your loop processes every element and prevents the common off-by-one error where the last item is missed. Keep an eye on this whenever you're iterating through a list by index.
Real-world applications
Now that you understand how to avoid common errors, you can apply range() to practical tasks like batch processing and building coordinate grids.
Using range() for batch processing data
The step argument in range() lets you efficiently slice large datasets into smaller chunks, a technique known as batch processing.
data = list(range(1, 21)) # Sample data with 20 items
batch_size = 5
for i in range(0, len(data), batch_size):
batch = data[i:i+batch_size]
print(f"Processing batch {i//batch_size + 1}: {batch}")
This code processes a list in fixed-size groups. By setting the step argument in range() to match the batch_size, the loop generates only the starting index for each chunk. This allows you to jump through the data instead of iterating one item at a time.
- The loop provides the indices
0,5,10, and15. - List slicing,
data[i:i+batch_size], uses these indices to pull out each five-item segment.
This technique gives you a clean way to handle data in manageable portions.
Creating a simple coordinate grid with range()
By nesting two range() loops, you can easily generate coordinates for a 2D grid, with each loop controlling one axis.
grid_size = 3
for y in range(grid_size):
for x in range(grid_size):
coordinate = (x, y)
print(f"{coordinate}", end=" ")
print() # New line after each row
This snippet uses nested for loops to generate a 3x3 coordinate grid. The outer loop iterates through each row. For every single row, the inner loop runs completely to generate all the column values for that specific row. This structure is key to building 2D data representations.
- Each
(x, y)coordinate is printed on the same line becauseend=" "prevents a newline. - The final
print()call is what moves the cursor down, starting the next row on a new line.
Get started with Replit
Turn your knowledge of range() into a real tool. Give Replit Agent a prompt like: "Build a prime number generator up to 1,000" or "Create a script that renames files with sequential numbers."
Replit Agent writes the code, tests for errors, and deploys the app for you. Start building with Replit.
Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.
Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.



