What we would like is a way to organize repetition.
We will do this using one version (there are many)
of the for-loop, one of the most important programming constructs:
def print_big_M():
print('* *')
print('** **')
print('* * *')
print('* *')
print('* *\n')
def print_big_O():
print('*****')
print('* *')
print('* *')
print('* *')
print('*****\n')
print_big_M()
for i in range(6):
print_big_O()
3.1 Exercise:
Type up the above in
animal_sounds_loop.py
and run it.
Also save the file so that it can be submitted
(You will need to save the appropriate files for every
such "type up" exercise).
3.2 Exercise:
Using the example above as a point of reference, print out your own animal sound. Be sure to use a for-loop to repeatedly print one letter in the sound.
Write your code in
my_pet_sound_loop.py.
Let's zoom in on the for-loop and examine it.
To do so, we'll write a different for-loop:
for i in range(6):
print(i)
3.3 Exercise:
Type up the above in
my_forloop_example.py
and run it. You should observe this:
0
1
2
3
4
5
In the place in the code where you see the number 6, replace 6 with
10 and then run the program.
Next, try 2 instead of 6. Finally, try 0 instead of 6.
What is the output in each case?
Report in your module pdf
(module3.pdf).
Submit the program with 6.
Let's now examine elements of the loop:
There's the special word
for:
Then, there's the for-loop variable
i:
The special word
in:
The element that controls the spread of different values that
variable
i
takes on at each iteration of the loop:
in:
The colon at the end:
Finally, the block of code (in this case, just one line)
that's called the body of the loop:
Let's change the program slightly and then set about explaining
how the loop works:
for i in range(6):
print(i)
print('Hello')
3.4 Exercise:
Type up the above in
my_forloop_example2.py
and run the program.
Observe that the body of this for-loop has two statements:
Let's now use a slightly fictionalized way to
explain the action of this loop:
Think of the Python part of your computer (since your laptop
does many things) as reading your program and then carrying out
the instructions.
When it encounters the
for
word, it says "Ah, here's a for-loop".
Then it sees the variable
i
and says (to itself), "This is the variable whose value
will change after each iteration".
Then it sees the term
range(6)
and says "Oh, i will start at 0 and end just before 6,
which means it will be 0 in the first iteration, 1 in the second,
2 in the third, 3 in the fourth, 4 in the fifth, 5 in the last".
Then, it starts executing the body of the loop for
the first iteration:
For the first iteration, i=0.
The entire body of the loop executes with i being replaced
by 0:
For the second iteration, i=1
Third iteration:
Fourth iteration:
Fifth iteration:
Sixth and final iteration:
Now the for-loop is done and the execution goes past the
whole for-loop to whatever's there.
In this case, there's no other code and the program completes.
3.5 Video:
3.1 Variations
To explore for-loops further, we'll look at some
variations of the basic for-loop:
First, we could have named our for-loop variable
for count in range(6):
print(count)
Note: it's customary to use short variable names like
i and j.
To go through a loop five times, any range of numbers
will do:
for i in range(10, 16):
print(i)
Note:
Here, the
range
feature has both a starting value (10) and just-after-ending value (16)
specified.
This will print the numbers 10 through 15.
We don't have to increment the for-loop variable by 1.
for i in range(10, 16, 2):
print(i)
This prints the numbers 10, 12, 14.
The number 2 in
range(10, 16, 2)
specifies an increment amount.
Thus, we start with i taking the value 10 in the first iteration.
In the second iteration, i becomes 12 (because 10+2 = 12).
In the third iteration, i becomes 14 (incrementing 12 by 2).
If we were to increment 14 by 2 it becomes 16 which is past
the last value allowed.
Important: think of 16 as "the variable cannot have
this value or anything past this value".
We can decrement, as in:
for i in range(16, 10, -1):
print(i)
This will print 16, 15, 14, 13, 12, 11.
We start with 16 (the first part of the range).
After each iteration we apply the increment/decrement amount.
In this case, applying -1 to 16 gives us 15, which gets printed.
Then, the third time through, i becomes 14. And so on.
In the last iteration, i becomes 11.
Finally, when i is decremented to 10, the loop is ended.
3.6 Exercise:
Type up the above four examples in
my_forloop_variation1.py,
my_forloop_variation2.py,
my_forloop_variation3.py,
and
my_forloop_variation4.py.
Run to confirm the output.
3.7 Exercise:
In
count_odd_up.py,
write a loop to print the odd numbers from 1 to 25
(thus, skipping by 2, and including 1 and 25 in the output).
3.8 Exercise:
In
count_even_down.py,
write a loop to print the even numbers from 24 down to 2 (inclusive of
24 and 2).
3.9 Video:
3.2 Nested for-loops
We'll start by writing a program to print a little
number triangle like this:
1
22
333
4444
Notice: there's repetition across a row of numbers:
a potential use of for-loops!
We'll do this in stages, starting with this program:
print(1) # print 1 all by itself
for i in range(2): # i will start at 0, go up to 1
print(2, end='')
print() # Print nothing but go to the next line.
for i in range(3): # i ranges from 0 to 2
print(3, end='')
print()
for i in range(4): # i ranges from 0 to 3
print(4, end='')
print()
Observe:
We've used end=''
(two single quotes in succession) to
avoid printing each number on a single line.
One could use two double quotes in succession as well.
print() merely goes to the next line.
(Or, stated differently, ends the current line being printed.)
3.10 Exercise:
Add a row for 5 (with five of
them), writing your code in
my_forloop_print.py
3.11 Exercise:
Just for the
heck of it, could one use a for-loop to achieve
the printing of 1 all
by itself? That is, answer the
question in your module pdf:
can a for-loop be set up so that you go
into it exactly once?
Write your code in
my_forloop_print2.py
Next, observe that the upper-limits of the for-loops are
themselves increasing:
Also, observe that the very thing we're printing across a
row is the loop limit itself:
Another way to say this:
When the value is 2, print a row of two 2's
When the value is 3, print a row of three 3's
When the value is 4, print a row of four 4's
Thus, we could try to do is:
for j in range(2, 5): # let j iterate from 2 to 4
# print j occurences of j using a loop
But we already know how to print a row of j's:
for j in range(2, 5): # let j iterate from 2 to 4
# print a row of j's (j of them)
for i in range (j):
print(j, end='')
Let's put this together in a complete program:
print(1) # print 1 all by itself
for j in range(2, 5): # j iterates from 2 to 4
for i in range(j): # for each j, print j of them
print(j, end='')
print()
3.12 Video:
3.13 Exercise:
Change the program to print a fifth row
with five 5's.
Also adjust the for-loop so that the for-loop
also takes care of printing
the sole 1
that appears in the row of
the sole 1's.
That is, adjust the for-loop conditions so that you don't
need the stand-alone print(1) to print 1.
Write your code in
my_forloop_print3.py
Let's review what we learned above:
The outer loop variable's value is used in the inner loop:
Consider a single iteration of the outer-loop
(e.g., when j is 3).
For this value of j, the inner loop executes
j times.
Thus, when j is 3, the inner loop
has 3 iterations.
This is an example of a nested for-loop in
which the inner loop's execution depends on the
value of the outer-loop variable.
Another way to say it: a nested for-loop
has one for-loop inside another.
We will use nesting in other contexts as well, when
one structure is placed inside another.
3.3 Tracing through a program in detail
We'll now look at an example of how to execute a program
"by hand". That is, how to trace a program's execution
by painstakingly following its execution step-by-step.
At first this will appear tedious, but it
is critical to a firm understanding of how programs
execute, and eventually to your own writing of programs.
We'll first do a longer, more narrative version here, and then
show you how to submit a much shorter version for your exercises.
For our example, let's look at the program we last saw:
print(1)
for j in range(2, 5):
for i in range(j):
print(j, end='')
print()
Let's now dive into the longer version, just for the sake of understanding.
To make best use of this:
Open this same page in another browser, and have the program
side-by-side, as you read what's below.
Read out aloud what you see below.
Ready? Let's trace through:
Right at the start, the first line is
print(1).
This prints out 1, and moves to the next line.
Initially j=2 at the start of the outer for-loop:
Since j is 2, it's within the range, and we enter the outer for-loop.
Now we encounter the inner for-loop, where i is set to 0
Note: when
range has only
one number specified, it's understood to be the upper limit.
The upper limit is the current value of j, which
is 2.
Inside the inner loop, we execute
print(1),
which, because j is now 2, will print 2.
We're at the end of the inner loop, so now i increments to 1:
So now inside the inner-loop, we print 2 again
Then, at the end of the inner for-loop, we return
to the top where i increments to 2.
Since i is at the limit, we exit the inner for-loop.
Notice: the inner loop iterated twice.
Next, we go past the inner loop to
print(),
which goes to the beginning of the next line.
This completes the first iteration of the outer,
after which we go to the top of the outerloop and increment j.
Execution now enters the outerloop with j set to 3.
Now we encounter the inner for-loop, where i is set to 0
The upper limit is the current value of j, which
is 3.
So, the inner loop executes three times, with i first set
to 0, then to 1, then to 2.
This will result in printing three 3's.
When i becomes 3, it hits the inner-loop limit and proceeds
to the
print()
that follows.
The output so far is:
1
2 2
3 3 3
This completes the iterations of the inner loop with
the outer loop j set to 3.
Next, j becomes 4
The inner loop starts with i set to 0.
Each time through i increments.
Until i hits the limit j (which is 4 now).
This results in four 4's being printed in a line.
Then we come out of the inner loop and execute
print(),
which goes to the next line.
The output so far is
1
2 2
3 3 3
4 4 4 4
Finally at the end of the outer loop, j becomes 5 and hits
the limit of the outer loop
Yes, that was long. But doing this many times will help
you understand how to read programs. Later, you will become
good at this and will, with a quick glance at the inner-loop,
say "Oh, this prints 2 twice in the first iteration of the outer."
Important: when you need to submit a program's traced-out
execution, use a shorter version. For example,
see this PDF for the above program.
3.14 Exercise:
Consider this program:
for i in range(1, 6):
for j in range(i, 0, -1):
print('*', end='')
print(' ', end='')
for j in range(1, i):
print('-', end='')
print()
First, trace through the values of i and j by hand
and try to figure out what gets printed. Do this painstakingly
for each possible value of i and j, remembering that i is now
the name of the outerloop variable.
Write your tracing in
module3.pdf,
using the shorter "table" format we
saw in this example
earlier.
Then, edit, compile and
execute the above program in
my_forloop_trace.py.
to see if you were right.
3.15 Video:
3.16 Exercise:
Write a program to print out consecutive integers in a diagonal,
as in
1
2
3
4
5
Use a nested for-loop as in earlier examples to print the
requisite number of spaces before printing a digit.
Write your code in
my_diagonal_print.py
3.17 Exercise:
Write a program to print out
I'm feeling cold: b rrrrrr rrrrr rrrr rrr rr r
Use a regular print
to print everything up to the b.
Then, use a nested for-loop for the r's.
Don't forget the space between each grouping of
r's.
Write your code in
my_brr_print.py
3.18 Video:
3.4 Reading and writing
Let's consider how to read a single for-loop, such as:
for k in range(1, 10, 2):
print(k, end=' ')
print(2*k)
print('-')
3.19 Exercise:
Write up the above in
my_simpleloop.py
and run to see the output. Then in
module3.pdf,
trace the execution of the program.
Instead of explaining the execution, let's focus on how
to read such a program:
The first thing to do is to observe two parts to the loop:
Next, study the for-statement to understand the nature of
of the iteration:
Now look inside the body:
Let's also point out what to keep in mind when writing:
First, the for-loop header or for-statement:
Next, the loop body:
Important: we will be nitpicky about writing
because good writing habits will save you a lot of trouble.
Next, let's combine reading with mental execution.
Consider the following program:
def functionOne():
print('*', end='')
def functionTwo():
print('*')
def functionThree():
for j in range(0, 5):
functionOne()
functionTwo()
for i in range(1, 11, 2):
functionThree()
3.20 Exercise:
What does it print? Try to figure this out by
mental execution first. Then, type it up, compile and
execute to confirm, writing your code in
my_execution_exercise.py.
Then in module3.pdf,
trace the execution of the program.
3.21 Video:
3.5 When things go wrong
As code gets more complex, it gets easier to make mistakes,
and harder to find them.
In each of the programs below, try to determine
the error without compiling the program. Then,
write up the program, compile and see what the
compiler says. After that, fix the error.
3.22 Exercise:
for i in range(0 6):
print(i)
Write your corrected code in
my_loop_exercise1.py.
3.23 Exercise:
for i in range(0, 6)
print(i)
Write your corrected code in
my_loop_exercise2.py.
3.24 Exercise:
for i in range(0, 6:
print(i)
Write your corrected code in
my_loop_exercise3.py.
3.25 Exercise:
for i in range(0, 6):
print(i)
Write your corrected code in
my_loop_exercise4.py.
3.26 Exercise:
for in range(0, 6):
print(i)
Write your corrected code in
my_loop_exercise5.py.
3.27 Exercise:
for i in range(0, 6):
print i
Write your corrected code in
my_loop_exercise6.py.
Let's point out the difference between
a syntax error and a logical error:
A syntax error will not allow a program to run.
This means you are using the language incorrectly.
On the other hand, you could have a program that has
no syntax errors (it runs) but it does not produce the
desired output. This means there's a logical error.
The process of identifying and fixing logical
errors is called debugging.
A bug is a logical error.
3.28 Exercise:
The following code intends to print
55555
4444
333
22
1
for i in range(5, 0, 1):
for j in range(1, i):
print(i, end='')
print()
But there are two bugs. First,
try to find the problems solely by reading and
mental execution.
Then, type up the program in
my_loop_exercise7.py.
What does it print?
Report what you see in
module3.pdf.
Then fix the program to get the desired output.
3.6 A peek at the future
Consider the following program:
import tkinter as tk
window = tk.Tk()
canvas = tk.Canvas(master=window, width=200, height=100)
canvas.pack()
def draw_rectangles():
for i in range(10, 51, 10):
canvas.create_rectangle(
3*i, i, 3*i+20, i+10, outline="blue")
draw_rectangles()
window.mainloop()
3.29 Exercise:
Download the above program,
my_forloop_rectangle.py,
and execute the program.
If you're feeling brave, add a second for-loop so that output
looks like:
Let's point out the for-loop's part in the program:
First, we need to understand how coordinates work differently
in Python:
Next, let's read the for-loop statement to see how
it iterates:
We can see that i will be 10 the first time through the loop.
Then i becomes 20, then 30 etc until 50.
Thus, there are 5 iterations through the loop.
Notice how i is used in the calculation of the measurements
needed to draw the rectangle:
(We spilled a line of code over two lines to make the font large
enough.)
When i is 10, the first rectangle's top left corner
gets drawn at 30 (which is 3 times i, or 3*i) from the left side,
and 10 down from the top.
In the second iteration i is 20, which means the top left
corner is 60 from the left. And so on.
3.30 Exercise:
Download
my_forloop_rectangle2.py,
and execute the program to see that an animation is really a for-loop.
About animations:
Even if an object moves across a screen (and is in different
positions on the screen), there is something that "repeats".
What repeats is the drawing of the object in different
places (with a gap in time to create the illusion of real movement).
Thus, when locations can be calculated we can
use a loop to iterate through the different positions.
This is essentially how animation works.
3.7 Some things to keep mind
Let's introduce the notion of reserved words:
Some words like
for
and
in
are special to the language and are called reserved words
or key words of the language.
There are special rules associated with the usage of
such reserved words, which we'll describe over time. For now,
we're just pointing them out.
Another example of a reserved word we've seen:
def
It turns out that, even though
print
looks like it should be a reserved word, it's in fact not.
At this stage, the distinction is not clear and that's fine.
As you learn the language, you'll learn how to distinguish.
Counting from 0:
When a single number like 6 is specified in the
range
as in
range(6),
Thus, i is 0 the first time, then 1, then 2, and so on until
i = 5 (last time through).
The number 6 specifies that i cannot be 6 or higher.
Thus, there is a certain strangeness to get used to:
Unlike math (where counting starts from 1), in programming,
the convention is to start from 0.
(Did you notice that's why we started with Module 0?)
The other strangeness is specifying the limit as one higher (6)
than than last iteration value (5).
The different uses of
range:
When a single number is specified, as in
range(6),
the implied start is 0.
When two numbers are specified as in:
range(10, 16),
the first is the start of the count, and the second is the limit:
Thus i is 10 the first time (this is the first thing that's printed).
Then i becomes 11.
Then 12, and so on until the last time through when i is 15.
When three numbers are specified as in
range(10, 16, 2),
the third number is the increment.
Here, i starts as 10 in the first iteration.
Then, i is 12 in the second iteration.
Then i becomes 14. This is the last iteration because
after that i would be 16, which ends the loop.
Using
range(10, 15, 2)
produces the same result as above, and in fact preferable.
About comments:
First, comments are for us to read. The computer does not read them.
Thus, in terms of execution, this program
# list the even numbers between 10 and 14, inclusive:
for i in range(10, 15, 2): # Notice the increment
print(i)
will result in the exact output as this one:
for i in range(10, 15, 2):
print(i)
We will use comments in two ways, as in the above example:
The first comment is an example of using a comment
as a prelude to code, to explain what's coming or intended.
The second kind that is to the right side of a line of code
is like an alert: we'll use this to point out something to pay
attention to in that line of code.
3.8 Meta
We will occasionally step back from the details to comment
on how best to learn.
This module was a bit different, a little more challenging than
modules 1-2.
What to keep in mind:
It is only natural to feel like you are in an alien
landscape.
⇒
You would feel no different doing the first few modules
while learning a foreign language with an entirely different script.
It takes a while to absorb some of the details, and that's
just fine.
Notice that some exercises were significantly
more challenging than others:
In prior modules, you merely typed in something and tried
it out, or make a small change.
With some exercises (like brrrrr) you had to do it all from scratch.
Both involved problem-solving ⇒
Taking a problem described in words and finding a solution.
Problem-solving is a higher-level skill than programming.
It takes time to acquire this skill.
There is no magic formula or words to simply make "problem
solving" work for you.
The only way is to develop this skill is to struggle with
problems, and with lots of them.
Finally, think about this:
Anyone can acquire both programming and problem-solving
skills with sufficient dedication. So why not you?
If you get past these hurdles with determination, you will
leave in the dust all those who gave up earlier.