In Python, the range() function generates a sequence of numbers, often used in loops for iteration. By default, it creates numbers starting from 0 up to but not including a specified stop value. You can also reverse the sequence with reversed(). If you need to count backwards, then you can use a negative step, like range(start, stop, -1), which counts down from start to stop.
The range() function is not just about iterating over numbers. It can also be used in various programming scenarios beyond simple loops. By mastering range(), you can write more efficient and readable Python code. Explore how range() can simplify your code and when alternatives might be more appropriate.
By the end of this tutorial, you’ll understand that:
- A range in Python is an object representing an interval of integers, often used for looping.
- The
range()function can be used to generate sequences of numbers that can be converted to lists. for i in range(5)is a loop that iterates over the numbers from 0 to 4, inclusive.- The range parameters
start,stop, andstepdefine where the sequence begins, ends, and the interval between numbers. - Ranges can go backward in Python by using a negative step value and reversed by using
reversed().
A range is a Python object that represents an interval of integers. Usually, the numbers are consecutive, but you can also specify that you want to space them out. You can create ranges by calling range() with one, two, or three arguments, as the following examples show:
>>> list(range(5))
[0, 1, 2, 3, 4]
>>> list(range(1, 7))
[1, 2, 3, 4, 5, 6]
>>> list(range(1, 20, 2))
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
In each example, you use list() to explicitly list the individual elements of each range. You’ll study these examples in more detail later on.
A range can be an effective tool. However, throughout this tutorial, you’ll also explore alternatives that may work better in some situations. You can click the link below to download the code that you’ll see in this tutorial:
Get Your Code: Click here to download the free range() sample code that shows you how to represent numerical ranges in Python.
Python for Beginners Live Course: Want more practice with loops, ranges, and the rest of Python’s building blocks? In Real Python’s Python for Beginners live course, you build real programs with an instructor and a small group of fellow learners. Join the waitlist to hear about the next dates.
Construct Numerical Ranges
In Python, range() is built in. This means that you can always call range() without doing any preparations first. Calling range() constructs a range object that you can put to use. Later, you’ll see practical examples of how to use range objects.
You can provide range() with one, two, or three integer arguments. This corresponds to three different use cases:
- Ranges counting from zero
- Ranges of consecutive numbers
- Ranges stepping over numbers
You’ll learn how to use each of these next.
Count From Zero
When you call range() with one argument, you create a range that counts from zero and up to, but not including, the number you provided:
>>> range(5)
range(0, 5)
Here, you’ve created a range from zero to five. To see the individual elements in the range, you can use list() to convert the range to a list:
>>> list(range(5))
[0, 1, 2, 3, 4]
Inspecting range(5) shows that it contains the numbers zero, one, two, three, and four. Five itself is not a part of the range. One nice property of these ranges is that the argument, 5 in this case, is the same as the number of elements in the range.
Count From Start to Stop
You can call range() with two arguments. The first value will be the start of the range. As before, the range will count up to, but not include, the second value:
>>> range(1, 7)
range(1, 7)
The representation of a range object just shows you the arguments that you provided, so it’s not super helpful in this case. You can use list() to inspect the individual elements:
>>> list(range(1, 7))
[1, 2, 3, 4, 5, 6]
Observe that range(1, 7) starts at one and includes the consecutive numbers up to six. Seven is the limit of the range and isn’t included. You can calculate the number of elements in a range by subtracting the start value from the end value. In this example, there are 7 - 1 = 6 elements.
Count From Start to Stop While Stepping Over Numbers
The final way to construct a range is by providing a third argument that specifies the step between elements in the range. By default, the step is one, but you can pass any non-zero integer. For example, you can represent all odd numbers below twenty as follows:
>>> range(1, 20, 2)
range(1, 20, 2)
Here, you specify that you want a range of numbers from one to twenty that are two apart. Have a look at the numbers that are part of this range:
>>> list(range(1, 20, 2))
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
You can confirm that the range contains all odd numbers below twenty. The difference between consecutive elements in the range is two, which is equal to the step value that you provided as the third argument.
In these examples, you’ve gotten started using ranges in Python. In the rest of the tutorial, you’ll learn more about how range() works under the hood, and you’ll see several examples of when you’d want to use range objects in your own code.
Use Python’s range() Function to Create Specific Ranges
You’ve seen the syntax of range() and how you use one, two, or three arguments to specify different kinds of ranges. In this section, you’ll dig deeper into Python’s range() function and see how to represent specific ranges.
Note: Technically, range() is not a function. Instead, range is a type or class. When you call range(), you’re calling the constructor of the range class to create a new range object.
Still, for all practical purposes, you can treat range() as a function that returns a range object.
First, note that a range is a lazy sequence. This means that Python doesn’t create the individual elements of a range when you create the range. Instead, it creates each element when you ask for it, for example by iterating over the range.
This is different from, say, a list. Lists are eagerly constructed, so that all elements in the list are present in memory immediately when the list is created. That’s why you converted ranges into lists to inspect the individual elements earlier:
>>> range(1, 7)
range(1, 7)
>>> list(range(1, 7))
[1, 2, 3, 4, 5, 6]
The range object is lazy. In this example, the individual numbers in the range are first referenced when you convert it to a list. Additionally, you don’t exhaust ranges when you iterate over them. You can reuse them as many times as you want.
One property of ranges that may seem unintuitive is that the start value of the range is included, but the end value isn’t. Python ranges represent half-open intervals, to use a technical term.
Closed intervals, which include both the start and end values, are more common in daily use. For example, a regular dice has values from one to six. However, using half-open intervals in programming has several advantages,which Edsger W. Dijkstra outlines as follows:
- If the start value isn’t included in the range, then you’d need to use
-1to specify a range running from zero. - If the end value is included in the range, then it’s awkward to define an empty range.
- If the range is defined as a half-open interval, then it’s straightforward to calculate the number of elements in the range.
You’ve already seen a few examples of the latter point. Recall that range(1, 7) contains six elements which you calculate as 7 - 1 = 6. Next, you’ll explore how to create special kinds of ranges.
Handle Ranges Over Negative Numbers
Probably, most of the ranges that you’ll construct will consist of positive numbers. If you only provide one argument when you create a range, then, as you’ve learned, the range counts from zero and up.
However, nothing’s stopping you from using negative numbers in your ranges. For example, you can create the numbers from negative ten to zero:
>>> range(-10, 0)
range(-10, 0)
>>> list(range(-10, 0))
[-10, -9, -8, -7, -6, -5, -4, -3, -2, -1]
Using negative numbers as arguments works similarly to positive numbers. The first element in the range is the start, while the second one is the end, as usual. You can use negative values for both arguments. Here are the numbers from negative seven to negative three:
>>> range(-7, -3)
range(-7, -3)
>>> list(range(-7, -3))
[-7, -6, -5, -4]
As always, the end value isn’t included in the range. You can still calculate the number of elements by looking at the difference of the arguments. Just keep track of the negative signs: (-3) - (-7) = 4.
Work With an Empty Range
You can use any integer as a value for the first two arguments. However, many choices will lead to empty ranges. In particular, if the arguments are equal, then you know that the corresponding range will have zero elements. In other words, it’ll be empty:
>>> range(1, 1)
range(1, 1)
>>> list(range(1, 1))
[]
Here, you construct a range starting at 1. Since 1 is also the end of the range, it’s not included, so the range is empty.
In general, an empty range isn’t particularly useful. You probably won’t create an empty range explicitly. However, if you’re working with ranges with dynamic arguments, then some of those arguments may lead to an empty range.
As you’ve learned, there are many ways you can create an empty range. If you need to create one explicitly, then the clearest is probably one counting from zero to zero:
>>> range(0)
range(0, 0)
>>> list(range(0))
[]
You confirm that range(0) represents an empty range.
If your first argument is larger than the second one, then you’ll typically end up with an empty range as well:
>>> range(4, 2)
range(4, 2)
>>> list(range(4, 2))
[]
Here, you’ve constructed a range that runs from four and up to two. Since four is larger than two, there are no numbers in that range.
Sometimes, you want to count down from a larger number. That’s what you’ll explore next.
Count Backward With Negative Steps
So far, you’ve looked at ranges with positive steps. By default, ranges use a step equal to one, but you can use any integer except zero. The following range contains all even numbers from twenty and down to zero:
>>> range(20, 0, -2)
range(20, 0, -2)
>>> list(range(20, 0, -2))
[20, 18, 16, 14, 12, 10, 8, 6, 4, 2]
By using a negative step, the range counts down from start to stop. As always, the stop isn’t included.
Just as most positive ranges use the default step of one, a step value of negative one is common when counting backward:
>>> range(5, -1, -1)
range(5, -1, -1)
>>> list(range(5, -1, -1))
[5, 4, 3, 2, 1, 0]
This range represents counting down from five to zero, inclusive. If you use a negative step, then the range will be empty if the second argument is larger than or equal to the first.
To practice choosing a range’s arguments yourself, write a function that returns every floor an elevator passes between its starting floor and its destination, both included, going up or down:
You’ve seen that you can use any integer value for the arguments, although the last one can’t be zero. In the next section, you’ll look into some practical use cases where you can loop through a range, as well as situations in which an alternative may be more appropriate.
Loop Through Ranges or Use an Alternative
In Python, you can create loops using two different constructs:
- A
whileloop, or an indefinite loop, repeats an operation until a condition is fulfilled. - A
forloop, or a definite loop, repeats an operation for each element in an existing sequence.
Since a range is a sequence, you typically use for loops to iterate over ranges.
In many languages, including C++, Java, and JavaScript, for loops are mainly based on indices. Python loops are different. In Python, a for loop is based on sequence elements instead of indices. If you’re more familiar with a different language, you may need to adjust how you approach loops.
In particular, if you want to re-create an index-based loop, then you may be tempted to use a range:
>>> word = "Loop"
>>> for index in range(len(word)):
... print(index, word