Preparation#

Reading material#

In the Think Python (TP) book, loops are covered in Chapter 7 Iteration and Search. However, the book shows looping on strings which we haven’t studied yet, and it explains only for-loops, but in the course, we teach both the for-loop and the while-loop.

Therefore, this week is better aligned with the lecture notes of the CS50 course, Lecture 2 Loops, first three sections.

Copy-and-Run#

Explanation of the Copy-and-Run exercises. In Copy-and-Run (CaR) exercises, you’ll copy the provided code into Python, run it, and observe the output. Try to understand why the code produces that result and if possible, predict the output before running it.

Prep 4.1: Basic for-loop#

For each of the code blocks below, try to predict what will be printed. Then run the code to see if you were right.

for i in range(3):
    print("Hello!")
for i in range(5):
    print(i)
for i in range(4):
    print(i, "Hello!")

As you can see, writing for i in will make the code loop (repeat), and the variable i will change its value each time the body of the loop is executed. The text written to the right of for i in determines which values i will take. Here i is called the iteration variable, and it is common to use i or idx as the name. However, you can use any name you want.

Sometimes we use the iteration variable in the loop body, but sometimes we don’t. Look at the examples above and determine which of them use the iteration variable in the loop body.

Prep 4.2: range#

For now, we will always use range in for-loops. Later, you will learn about other ways of defining for-loops. To learn about range, run the following code.

start = 0
stop = 10
step = 1
for i in range(start, stop, step):
    print(i)

Now change the values of start, stop, and step using the following values, and run the code again. Try to predict the output before running the code.

  • start = 1, stop = 11, step = 1

  • start = 0, stop = 11, step = 2

  • start = 10, stop = 0, step = -1

  • start = 1, stop = 1, step = 1

As you can see, range will increase the iteration variable by the value of step, and will stop before reaching the value of stop.

With this knowledge, use the code above but change the values of start, stop, and step to achieve the following:

  1. Print numbers from 1 to 10: 1, 2, …, 10.

  2. Print even numbers from 0 to 10: 0, 2, 4, …, 10.

  3. Print a countdown from 10 to 0: 10, 9, …, 0. Hint: you can use a negative step size.

  4. Print the numbers: 17, 21, 25. Hint: use an appropriate step size.

  5. Print multiples of 5: 0, 5, 10, 15, …, 45, 50.

  6. Don’t print anything.

Prep 4.3: Default behavior of range#

Now, try running run each of the following code blocks and see what they print.

for a in range(5):
    print(a)
for a in range(0, 5):
    print(a)
for a in range(0, 5, 1):
    print(a)

Change the values of start, stop, and step in the code above and confirm that:

  • If you give 3 arguments to range, they will be interpreted as start, stop, and step.

  • If you give 2 arguments, they will be interpreted as start and stop, with step = 1 assumed.

  • If you only give 1 argument, it will be interpreted as stop, with start = 0 and step = 1 assumed.

Prep 4.4: Using the iteration variable in expressions#

For each of the code blocks below, try to predict what will be printed. Then run the code to see if you were right.

for j in range(3):
    print(j ** 2)
for times in range(1, 6):
    greeting = "Hello! " * times
    print(greeting)
import math
for n in range(2, 7):
    s = math.sqrt(n)
    print("The square root of", n, "is", s)

As you can see, you may use the iteration variable in expressions inside the loop body. For all the examples above, try to predict which variables are defined after the loop is executed, and what their values are. Test your predictions by running the code. What is the iteration variable in each of the examples? What is greeting after the loop in the second example? What is s after the loop in the third example?

Prep 4.5: Collecting values#

For each of the following blocks, try to predict what the code does. Which variables are defined after the loop is executed, and what are their values? Run the code to see if you were right.

current_sum = 0
for element in range(1, 11):
    current_sum = current_sum + element
print(current_sum)
text = ""
for n in range(10):
    text = text + str(n) + " "
print("After the loop, text is:")  
print(text)
current_sum = 0
for i in range(1, 11):
    s = i ** 2
    print("Square of", i, "is", s)
    current_sum = current_sum + s
print("The sum of squares is", current_sum)   

As you can see, we may use loops to collect something, like summing numbers or concatenating strings. For this, we need to initialize a variable before the loop, and then repeatedly update it inside the loop.

Prep 4.6: Basic while-loop#

For each of the code blocks below, try to predict what will be printed. Then run the code to see if you were right.

x = 0
while x < 10:
    print(x)
    x = x + 1
print("We are done and x is", x)
x = 10
while x > 0:
    print(x)
    x = x - 2
print("We are done and x is", x)
x = 1
while x <= 1000:
    print(x)
    x = x * 2
print("We are done and x is", x)

The while-loop will keep running as long as the condition is True. For each of the examples above, identify the condition. Now, identify the value of x before the loop is executed. What is the value of the condition before the loop is executed? Now, identify the value of x after the loop is executed. What is the value of the condition after the loop is executed?

Try changing the condition in the loops above so that the loop runs exactly 2 times.

Prep 4.7: Be careful with while-loops#

Now, try running this code.

x = 10
while x < 5:
    print(x)
    x = x + 1
print("We are done and x is", x)

As before, identify the value of x before and after the loop is executed. What is the value of the condition before and after the loop is executed? If the condition is not True before the loop is executed, the loop will not run at all!

You can also create a loop that will never end, a so-called infinite loop. Before you try that, you should know how to force a running program to stop.

Try to run the following infinite loop, and stop it by pressing ctrl+C or +C, which will result in a KeyboardInterrupt error.

j = 0
while True:
    print(j)
    j = j + 1

Warning

Certain versions of Python have a bug where the IDLE window freezes during an infinite loop, so it no longer responds to ctrl+C. If this happens, you can close the IDLE window and open it again. When we move to VS Code next week, this will not be an issue.

It happens that you sometimes accidentally create an infinite loop. Below, an example of an accidental infinite loop is given. Why will it never stop? Add a print statement to see the value of x in each iteration to figure out why it will never stop. Change just one character in the code to make the loop stop after 10 iterations.

x = 0
while x < 10:
    print("I'm running!")
    x = x - 1

Prep 4.8: More while-loops#

For each of the code blocks below, try to predict what will be printed. Then, run the code to see if you were right.

text = 'abe'
while text == 'abe':
    text = text + 'a'
text = 'abracadabra'
s = ''
while len(s) < len(text):
    s = s + 'a'

In the last example, we used the function len to determine the length of a string.

Prep 4.9: Breaking loops#

Try to predict what the following code does, then run it to see if you were right.

for i in range(100):
    print(i)
    if i >= 5:
        print("I am tired of looping!")
        break
max_iterations = 100
i = 0
while i < max_iterations:
    print(i)
    if i >= 10:
        break
    i = i + 1

If you want to exit a loop before it is finished, you can use the break statement.

Prep 4.10: Doing something once#

Run the following code to see what it does. Try to predict what the code does before running it.

balance = 950
meal_cost = 100
waiting = True
for day in range(100):
    balance = balance - meal_cost
    if balance < 0 and waiting:
        print("The balance is negative after", day, "days.")
        waiting = False
print("Final bank balance", balance)

Often, you want to do something in just one iteration, even if a loop keeps going. This can be done by using a boolean variable to keep track of whether this has already been done. In the example above, once waiting becomes false, the message will not be printed again, despite the balance being negative.

Prep 4.11: Nested loops#

Try to predict what the following code does, then run it to see if you were right.

for i in range(2):
    for j in range(3):
        print(i, j)
x = 0
for i in range(5):
    for j in range(6):
        x = x + 1
print("x is", x)

Loops may be nested, similar to nested if statements.

Now look carefully at this nested loop, and try to predict how many lines will be printed.

for i in range(4):
    for j in range(i):
        print(i, j)

If you are unsure about what this code does, it is a good idea to add some print statements to see when the loop body is entered and exited. For the last example, you could add print statements to get the code below.

for i in range(4):
    print("*-*-*-* START OF OUTER LOOP *-*-*-*")
    for j in range(i):
        print("*-* START OF INNER LOOP *-*")
        print(i, j)

As you can see, the first time the outer loop is entered, the inner loop is not entered at all. The second time the outer loop is entered, the inner loop is entered once, and so on. The last time the outer loop is entered, the inner loop is entered three times.

You can also use Python Tutor to visualize the flow of control. You can copy code from any exercise, paste it into Python Tutor, and run it to observe how the lines get executed.

Prep 4.12: Bad for-loop practices#

In for-loops, the iteration variable gets updated automatically for each iteration. It is a bad practice to change the value of the iteration variable inside the loop. This can lead to unexpected behavior. Try to predict what the following code does, then run it to see if you were right.

for i in range(5):
    print(i)
    i = i + 100 # Don't do this in your code!
    print(i)
print("The value of i after the loop is", i)

Another bad practice is to use the same variable name in nested loops. Run the code below to confirm that the code runs, but it may be difficult to understand how the value of i changes.

for i in range(1, 3):
    print(i)
    for i in range(11, 13): # Don't do this in your code!
        print(i)

Prep 4.13: Debug common looping errors#

Below we have several examples, which all contain syntax errors that will prevent the code from running.

For all the examples below, first try to find the error by reading the code. Then run the code to see what happens. Carefully read the error message. Finally, try to fix the error. We have provided hints for fixing the error, but you should try to fix the error without looking at the hints.

for i range(5):
    print(i)
for i in range(5):
    x = x + 1
month = "January"
for i in range(4, 14):
    # I don't care for all dates
print("Today is the "+str(i)+"th of " + month)

Prep 4.14: Predict the outcome#

For each of the loops below, predict:

  • How many lines will be printed?

  • What will be printed on each line?

Then run the code to see if you were right.

i = 5
for _ in range(3):
    print("Print A", i)
i = 5
for i in range(3):
    print("Print B", i)
for i in range(1, 10, 5):
    print("Print C", i)
for i in range(5):
    if i % 2 == 0:
        print("Print D", i)
x = 0
while x <= 10:
    x = x + 1
    if x > 8:
        print("Print E", x)
x = -1
while x < 99:
    x = x + 1
    if x == 1:
        break
    print("Print F", x)
x = -1234
while x < 0:
    x = x + 1
print("Print G", x)
x = 0
while x < 0:
    x = x + 1
    if x == 0:
        print("Print H", x)
        break
a = 0
b = 0
while a < 5 and b < 5:
    if a < b:
        a = a + 1
    else:
        b = b + 1
    print("Print I", a, b)

Self quiz#

Question 4.1#

What happens when running the following code?

for i in range(5):
    a = i
print(a)

Question 4.2#

How many lines will the following code print?

for i in range(1, 10):
    print("Do something")

Question 4.3#

Which is identical to range(5) ?

Question 4.4#

After the following code is executed, what is the value of x?

x = 0
for i in range(5):
    x = x + i

Question 4.5#

How many times will Please no spam :( be printed by the following code?

for i in range(3):
    for j in range(2):
        print("Please no spam :(")

Question 4.6#

How many lines will the following code print?

x = 0
while x < 5:
    x = 2 * x
    print("Do something")

Question 4.7#

What is the value of text after the following code is executed?

text = "Hello "
for r in range(1, 3):
    text = r * text 

Question 4.8#

Which values will m have during the execution of the following code?

a = 3
b = 6
for m in range(min(a, b), max(a, b)):
    print(m)

Question 4.9#

How many lines will the following code print?

x = 5
for i in range(10):
    if i > x:
        break
    print("Do something")

Question 4.10#

What is the value of i after the following code is executed?

i = 0
while i < 10:
    if i > 5:
        break
    i = i + 1

Question 4.11#

What is the value of x after the following code is executed?

x = 999
for x in range(5):
    break

Question 4.12#

What is the value of x after the following code is executed?

x = 3
while x > 0:
    x = x - 1

Question 4.13#

In a loop starting with for i in range(4, 8, 2):, which values will i have during the code execution?

Question 4.14#

What is the value of i after the following code is executed?

i = 0
while len(str(i)) < 5:
    i = i + 1

Question 4.15#

What will be printed by running the following code?

num = 1
while True:
    num = num + 1
    if (num % 5) == 1:
        break
print(num)

Question 4.16#

Which numbers will be printed by the following code?

a = 2
b = 5
for i in range(a, b + 1):
    print(i)

Question 4.17#

How many times will the following code print Hi Alice?

name = "Alice"
for i in range(len(name)):
    print('Hi ' + name)

Question 4.18#

Which value will s have after the following code is executed?

s = ''
for i in range(1, 6):
    s = s + str(i)

Question 4.19#

How many lines will the following code print?

for i in range(0, 6, 2):
    print("Line")

Question 4.20#

How many times lines will be printed by the following code?

for i in range(5):
    if i % 2 == 0:
        print("I've been executed")

Question 4.21#

What is the value of the variable x after the following code is executed?

x = 0
while (0 < x) and (x < 10):
    x = x + 1

Question 4.22#

How many lines will the following code print?

x = 0
while x < 4:
    x = x + 1
print(x)

Question 4.23#

What is the value of x after the following code is executed?

x = 0
while x < 109:
    x = x + 2

Question 4.24#

How many times will the following code print something?

weekend_soon = False
for days_till_weekend in range(5):
    if days_till_weekend < 3 and not weekend_soon:
        print("It's weekend soon!")
        weekend_soon = True