The range Function
Let's say you wanted to count to 100. It would be a pain to have list
each number out. The range function can make it much easier
to create and manage a for loop.
The range function is a built-in function in Python. We will learn more about functions in the next lesson. For now, functions are simply reusable bits of code that can be called when needed.
The range function helps us to create a sequence of integers. The creation is based on information, called an argument, which you pass into the range function.
Here's an example:
| Code | Sequence | Notes |
|---|---|---|
range(3) |
0, 1, 2 |
Start at zero and go up to, but not including, 3. |
range(5) |
0, 1, 2, 3, 4 |
Start at zero and go up to, but not including, 5. |
Here we have passed the integer 3 into the range function.
When we call range(3), we get the numbers 0, 1,
2.
Note that the first item in the sequence is a zero. And notice that the sequence goes up to, but does not include, 3.
We can use range(3) in a for loop like this:
| Code | Output |
|---|---|
for n in range(3): |
0 |
Of course, we don't want every sequence to begin with a zero. The
range function has other options as well, and you pass these into
the function too. Adding a second integer will allow you to control where
you start and where you stop.
| Code | Sequence | Notes |
|---|---|---|
range(1, 3) |
1, 2 |
Start at 1 and go up to, but not including, 3. |
range(2, 5) |
2, 3, 4 |
Start at 2 and go up to, but not including, 5. |
When we use range(2, 5) in a for statement, we
get:
| Code | Output |
|---|---|
for n in range(2, 5): |
2 |
Notice that the first integer passed into the range function
controls the starting integer in the sequence. The second integer passed
into the range function controls the ending integer - but again, it
is up to an not including that integer.
Finally, we might want to be able to skip count. Remember as a
kid? Counting to 100 by 10s? That was skip counting. Python
calls this the step. The third argument passed into the range
function controls the step in which the sequence is incremented or decremented
(because you can also go backwards!). Here are some examples:
| Code | Sequence | Notes |
|---|---|---|
range(1, 10, 2) |
1, 3, 5, 7, 9 |
Start at 1 and go up to, but not including, 10. Go up in steps of 2. |
range(5, 35, 4) |
5, 9, 13, 17, 21, 25, 29, 33 |
Start at 5 and go up to, but not including, 35. Go up in steps of 4. |
When we use range(1, 10, 2) in a for statement, we
get:
| Code | Output |
|---|---|
for n in range(1, 10, 2): |
1 |
Remember how you can go backwards? Just start at a higher number, stop at a lower number, and use a negative step.
| Code | Sequence | Notes |
|---|---|---|
range(10, 0, -2) |
10, 8, 6, 4, 2 |
Start at 10 and go down to, but not including, 0. Go down in steps of 2. |
Example: Countdown, Part 3
Here is how we can re-write the countdown program using the
range function:
for n in range(5, 0, -1):
print(n)
print('Blastoff!')
Output
5
4
3
2
1
Blastoff!
How it Works
| Code | Output | Explanation |
|---|---|---|
for n in range(5, 0, -1): |
5 |
Range creates a sequence. It starts at 5. The step argument (the last one) tells us to down by 1 until, but not including, the stop argument of 0. In other words: [5, 4, 3, 2, 1]
The |
print('Blastoff!') |
Blastoff! |
We display the word Blastoff! The program is finished. |
The arguments which are passed into the range function can be variables as well - just so long as they are integers. This allows more control over your program.
| Code | Sequence | Notes |
|---|---|---|
start = 5 |
5, 7, 9 |
Start at 5 and go up to, but not including, 10. Go up in steps of 2. |
x = 5 |
5, 9, 13, 17, 21, 25, 29, 33 |
Start at 5 and go up to, but not including, 35. Go up in steps of 4. |
This means that you have your user control the countdown program as well.
The break Statement
The break statement is used to break out of a loop
statement i.e. stop the execution of a looping statement, even if the loop
condition has not become False or the sequence of items has not
been completely iterated over.
For example, suppose you want to take input from the user until they type done. You could write:
while True:
line = input('Are you done? ')
if line == 'done':
break
print(line)
print('Done!')
The loop condition is True, which is always true, so the loop
runs until it hits the break statement.
Each time through, it prompts the user with the question Are you
done? If the user types done, the break
statement exits the loop. Otherwise the program echoes whatever the user types
and goes back to the top of the loop. Here’s a sample run:
Are you
done? not done
Are you done? done
Done!
This way of writing while loops is common because you can check the condition anywhere in the loop (not just at the top) and you can express the stop condition affirmatively ("stop when this happens") rather than negatively ("keep going until that happens").
An important note is that if you break out of a for or
while loop, any corresponding loop else block is
not executed.
Note that you can use break with the for statement
as well.
The continue Statement
The continue statement is used to tell Python to skip the rest
of the statements in the current loop block and to continue to the next
iteration of the loop.
For example:
for n in [1, 2, 3]:
if
n==2:
continue
print(n)
When we execute this code, we get:
1
3
So even though there is clearly a 2 in our list of 1, 2, 3, the 2 is
skipped. Why? In the body block of the for statement,
there is a conditional statement. The conditional is looking at whether
n = 2. When n = 2, the conditional uses the
continue statement to skip the rest of the body block of the
for statement and go straight to the next iteration. So, the
2 is never printed. It is skipped.
The better practice might be to leave the 2 out of your list, but it is nice
to know that you can use continue if you need it.
Note that you can use continue with the while
statement as well.
Nested Loops
Just as with conditional statements, you can also nest loops. You can
nest for loops in while loops and while
loops in for loops. You can nest for loops in
other for loops and while loops in other
while loops. What follows are some examples and ideas for
creating programs.
Example: Triangles
This code produces some pretty triangles:
for x in range(3):
for y in range(3, 0, -1):
print("|", " "*x, "*"*y)
Output
| ***
| **
| *
| ***
| **
| *
| ***
| **
| *
| ***
| **
| *
How It Works
| Code | Output | Explanation |
|---|---|---|
for x in range(4): |
None |
This is the outer |
for y in range(3, 0, -1): |
None |
This is the inner Because the inner |
print("|", " "*x,
"*"*y) |
This is the statement which changes during each iteration. Let's do these one at a time. When the outer |
Here are our iterations. Since the outer loop will run 4 times and the inner loop will run 3 times, there will be 12 total iterations:
| Iteration | x value | y value | print statement | Output |
|---|---|---|---|---|
| 1 | 0 | 3 | print("|", " "*0, "*"*3) |
| *** |
| 2 | 0 | 2 | print("|", " "*0, "*"*2) |
| ** |
| 3 | 0 | 1 | print("|", " "*0, "*"*1) |
| * |
| 4 | 1 | 3 | print("|", " "*1, "*"*3) |
| *** |
| 5 | 1 | 2 | print("|", " "*1, "*"*2) |
| ** |
| 6 | 1 | 1 | print("|", " "*1, "*"*1) |
| * |
| 7 | 2 | 3 | print("|", " "*2, "*"*3) |
| *** |
| 8 | 2 | 2 | print("|", " "*2, "*"*2) |
| ** |
| 9 | 2 | 1 | print("|", " "*2, "*"*1) |
| * |
| 10 | 3 | 3 | print("|", " "*3, "*"*3) |
| *** |
| 11 | 3 | 2 | print("|", " "*3, "*"*2) |
| ** |
| 12 | 3 | 1 | print("|", " "*3, "*"*1) |
| * |
Debugging
As you start writing bigger programs, you might find yourself spending more time debugging. More code means more chances to make an error and more places for bugs to hide.
One way to cut your debugging time is "debugging by bisection". For example, if there are 100 lines in your program and you check them one at a time, it would take 100 steps.
Instead, try to break the problem in half. Look at the middle of the program, or near it, for an intermediate value you can check. Add a print statement (or something else that has a verifiable effect) and run the program.
If the mid-point check is incorrect, there must be a problem in the first half of the program. If it is correct, the problem is in the second half.
Every time you perform a check like this, you halve the number of lines you have to search. After six steps (which is fewer than 100), you would be down to one or two lines of code, at least in theory.
In practice it is not always clear what the "middle of the program" is and not always possible to check it. It doesn’t make sense to count lines and find the exact midpoint. Instead, think about places in the program where there might be errors and places where it is easy to put a check. Then choose a spot where you think the chances are about the same that the bug is before or after the check.
