When working with loops, we often need to iterate over a sequence of numbers. For example, we might want to count from 0 to 9, or from 5 to 20, or maybe count by twos or threes. Python provides a built-in function called range() that generates a sequence of numbers for us.
The range() function is a special type in Python that represents an immutable sequence of numbers. It’s very memory-efficient because it doesn’t store all the numbers in memory at once—it generates them on demand. To see what numbers are in a range, we can convert it to a list using list(). Don’t worry about understanding lists right now—we’re just using list() as a tool to help us visualize what range() produces.
Immutable is an object that cannot be changed after it is created. We will talk more about list in the next section.
The simplest form of range() takes one argument. When range(n) is called, it generates numbers from 0 up to, but not including, n. This means it produces n numbers starting from 0 (inclusive) and up to n-1 (exclusive).
1
print(list(range(5)))
The output of this code is: [0, 1, 2, 3, 4]. Notice that it starts at 0 and goes up to 4 (not including 5). This gives us exactly 5 numbers: 0, 1, 2, 3, 4.
1
print(list(range(10)))
This will output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
What happens if we pass `0` or a negative number?
1
print(list(range(0)))
This does not produce anything. There are no numbers from 0 up to (but not including) 0, so the range is empty.
1
print(list(range(-5)))
This also does not produce anything. When the argument is negative, the range is empty because we can’t count from 0 up to a negative number.
When two arguments are provided to range(), the first argument is the starting value, and the second argument is the end value (which is not included). The syntax is range(start, end).
1
print(list(range(2, 8)))
This will output: [2, 3, 4, 5, 6, 7]. It starts at 2 and goes up to (but not including) 8, so we get 2, 3, 4, 5, 6, 7.
1
print(list(range(5, 10)))
This will output: [5, 6, 7, 8, 9].
1
print(list(range(0, 5)))
Passing the first argument as 0 is the same as using range(end).
What if the start is greater than or equal to the end?
What if the start is greater than or equal to the end?
1
print(list(range(5, 5)))
This does not produces anything. There are no numbers from 5 up to (but not including) 5.
1
print(list(range(10, 5)))
This also does not produce anything. When the start is greater than the end, and we’re counting forward (which is the default), the range is empty.
The third argument to range() is called the step. It controls how much we increment by each time. The syntax is range(start, end, step). By default, when a step is not specified, it’s 1, meaning we count by ones.
1
print(list(range(0, 10, 2)))
This will output: [0, 2, 4, 6, 8]. It starts at 0, goes up to (but not including) 10, and increments by 2 each time. So we get 0, 2, 4, 6, 8.
1
print(list(range(1, 10, 2)))
This will output: [1, 3, 5, 7, 9]. It starts at 1, goes up to (but not including) 10, and increments by 2, giving us all odd numbers from 1 to 9.
1
print(list(range(0, 20, 5)))
This will output: [0, 5, 10, 15]. It starts at 0, goes up to (but not including) 20, and increments by 5.
Using a step of 1 explicitly is the same as not specifying a step:
1
print(list(range(2, 8, 1)))
This is the same as range(2, 8) and produces: [2, 3, 4, 5, 6, 7].
When a negative step is used, the range counts backwards. In this case, the start should be greater than the end for the range to produce values.
1
print(list(range(10, 0, -1)))
This will output: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]. It starts at 10, goes down to (but not including) 0, decrementing by 1 each time.
1
print(list(range(20, 0, -2)))
This will output: [20, 18, 16, 14, 12, 10, 8, 6, 4, 2]. It starts at 20, goes down to (but not including) 0, decrementing by 2 each time.
1
print(list(range(5, -1, -1)))
This will output: [5, 4, 3, 2, 1, 0]. It starts at 5 and counts down to 0 (inclusive in this case because we’re going backwards and stopping before -1).
When using a negative step, make sure the start value is greater than the end value. If the start is less than the end when the step is negative, the range will be empty.
What happens if we try to count backwards but start is less than end?
1
print(list(range(0, 10, -1)))
This does not produce anything. We can’t count backwards from 0 to 10, so the range is empty.
Using negative numbers as arguments to range() works just like positive numbers, but the range will include negative values.
1
print(list(range(-5, 0)))
This will output: [-5, -4, -3, -2, -1]. It starts at -5 and goes up to (but not including) 0.
1
print(list(range(-10, -5)))
This will output: [-10, -9, -8, -7, -6]. It starts at -10 and goes up to (but not including) -5.
1
print(list(range(-10, 0, 2)))
This will output: [-10, -8, -6, -4, -2]. It starts at -10, goes up to (but not including) 0, incrementing by 2.
1
print(list(range(-1, -10, -2)))
This will output: [-1, -3, -5, -7, -9]. It starts at -1, goes down to (but not including) -10, decrementing by 2.
Below are some exercises to test your understanding of the range() function and its arguments.
Exercise 1: Range with one argument
What will this code output?
1
print(list(range(7)))
Answer:
The output will be: [0, 1, 2, 3, 4, 5, 6]
Exercise 2: True or False
Is the following statement true or false?
range(5) generates the numbers [0, 1, 2, 3, 4, 5].
Answer:
False. range(5) generates [0, 1, 2, 3, 4]. The range() function generates numbers up to, but not including, the end value. So range(5) includes 0, 1, 2, 3, 4 but excludes 5.
Exercise 3: Range with two arguments
What will this code output?
1
print(list(range(3, 9)))
Answer:
The output will be: [3, 4, 5, 6, 7, 8]
When range() is called with two arguments range(start, end), it generates numbers from start (inclusive) up to (but not including) end. So range(3, 9) starts at 3 and goes up to 8 (excluding 9).
Exercise 4: Multiple Choice Question
Which of the following will produce an empty range?
A: range(0)
B: range(5, 5)
C: range(10, 5)
D: All of the above
Answer:
D: All of the above
A: range(0) is empty because there are no numbers from 0 up to (but not including) 0.
B: range(5, 5) is empty because there are no numbers from 5 up to (but not including) 5.
C: range(10, 5) is empty because when counting forward (default step of 1), you cannot go from 10 to 5.
Exercise 5: Range with step argument
What will this code output?
1
print(list(range(0, 15, 3)))
Answer:
The output will be: [0, 3, 6, 9, 12]
When range() is called with three arguments range(start, end, step), it generates numbers starting from start, up to (but not including) end, incrementing by step each time. So range(0, 15, 3) starts at 0, increments by 3, and stops before 15, giving us 0, 3, 6, 9, 12.
Exercise 6: True or False
Is the following statement true or false?
range(2, 8, 1) produces the same result as range(2, 8).
Answer:
True. When the step is 1, it’s the same as the default step. So range(2, 8, 1) and range(2, 8) both produce [2, 3, 4, 5, 6, 7].
Exercise 7: Negative step
What will this code output?
1
print(list(range(10, 0, -2)))
Answer:
The output will be: [10, 8, 6, 4, 2]
When using a negative step, the range counts backwards. range(10, 0, -2) starts at 10, goes down to (but not including) 0, decrementing by 2 each time. So we get 10, 8, 6, 4, 2.
Exercise 8: Multiple Choice Question
Which range() call will produce [5, 4, 3, 2, 1]?
A: range(5, 0, -1)
B: range(5, 1, -1)
C: range(1, 6)
D: range(5, 0)
Answer:
A: range(5, 0, -1)
A: Correct. range(5, 0, -1) counts backwards from 5 down to (but not including) 0, decrementing by 1, producing [5, 4, 3, 2, 1].
D: range(5, 0) produces an empty range when counting forward (default step of 1).
Exercise 9: Negative numbers in range
What will this code output?
1
print(list(range(-5, 0)))
Answer:
The output will be: [-5, -4, -3, -2, -1]
Negative numbers work just like positive numbers in range(). range(-5, 0) starts at -5 and goes up to (but not including) 0, producing -5, -4, -3, -2, -1.
Exercise 10: True or False
Is the following statement true or false?
range(0, 10, -1) will produce numbers counting backwards from 10 to 0.
Answer:
False. range(0, 10, -1) produces an empty range. When using a negative step, the start value must be greater than the end value. Since 0 < 10, the range is empty. To count backwards from 10 to 0, you would use range(10, -1, -1).
Exercise 11: Multiple Choice Question
How many numbers does range(1, 20, 3) produce?
A: 6
B: 7
C: 19
D: 20
Answer:
B: 7
range(1, 20, 3) produces: [1, 4, 7, 10, 13, 16, 19]. Let’s count: starting at 1, incrementing by 3 each time: 1, 4, 7, 10, 13, 16, 19 (stops before 20). That’s 7 numbers.
Exercise 12: Range with negative step and negative numbers
What will this code output?
1
print(list(range(-1, -10, -2)))
Answer:
The output will be: [-1, -3, -5, -7, -9]
When using negative numbers with a negative step, range(-1, -10, -2) starts at -1, goes down to (but not including) -10, decrementing by 2 each time. So we get -1, -3, -5, -7, -9.
Exercise 13: Understanding range arguments
Which of the following range() calls will produce exactly 5 numbers?
range(10) produces the same numbers as range(0, 10).
Answer:
True. range(10) is equivalent to range(0, 10) because when only one argument is provided, it defaults to starting at 0. Both produce [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
Exercise 15: Range with step greater than difference
What will this code output?
1
print(list(range(1, 5, 10)))
Answer:
The output will be: [1]
When the step is greater than the difference between start and end, the range will only include the start value (if it’s less than the end). range(1, 5, 10) starts at 1, and since adding 10 would exceed 5 (the end), it only includes 1.
Exercise 16: Multiple Choice Question
What does range(2, 11, 2) produce?
A: All even numbers from 2 to 10
B: All odd numbers from 2 to 11
C: All numbers from 2 to 11
D: An empty range
Answer:
A: All even numbers from 2 to 10
range(2, 11, 2) produces [2, 4, 6, 8, 10], which are all even numbers from 2 to 10 (inclusive). The range starts at 2, increments by 2, and stops before 11.