Part 2

# Simple loops

We have now covered conditional structures in some detail. Another central technique in programming is repetition, or iteration. Together these form the fundamental control structures any programmer must master. They are called control structures because essentially they allow you to control which lines of code get executed when. While conditional structures allow you to choose between sections of code, iteration structures allow you to repeat sections of code. They are often called loops because they allow the program to "loop back" to some line that was already executed before. The process of executing one repetition of a loop is also referred to as an iteration of the loop.

This section introduces a simple `while` loop. Its structure is similar to the conditional statements we already covered. In the next part we will delve into some more sophisticated examples.

Let's have a look at a program which asks the user to type in a number and then prints out the number squared. This continues until the user types in -1.

``````while True:
number = int(input("Please type in a number, -1 to quit: "))

if number == -1:
break

print(number ** 2)

print("Thanks and bye!")``````

Running the program could look like this:

Sample output

Please type in a number, -1 to quit: 2 4 Please type in a number, -1 to quit: 4 16 Please type in a number, -1 to quit: 10 100 Please type in a number, -1 to quit: -1 Thanks and bye!

As you can see above, the program asks for several numbers, thanks to the `while` statement in the program. When the user types in -1, the `break` command is executed, which exits the loop and execution continues from the first line after the `while` block.

With loops, it is crucial that there is always a way to exit the loop at some point in the code, otherwise the repetition could go on forever. To illustrate this, let's change the above example a little:

``````number = int(input("Please type in a number, -1 to quit: "))
while True:
if number == -1:
break

print(number ** 2)

print("Thanks and bye!")``````

In this version the program asks the user to type in a number outside the loop. If the user types in any other number than -1, the loop is never exited from. This forms an infinite loop, which means the block of code within the loop is repeated endlessly:

Sample output

Please type in a number, -1 to quit: 2 4 4 4 4 4 4 4 4 (continued ad infinitum...)

The following program has a similar structure to the example above the infinite loop, but the user experience is quite different. This program allows the user to proceed only if they type in the correct PIN 1234:

``````while True:
if code == "1234":
break
print("Incorrect...try again")

print("Correct PIN entered!")``````
Sample output

## Loops and helper variables

Let's make the PIN checking example a bit more realistic. This version gives the user only three attempts at typing in a PIN.

The program uses two helper variables. The variable `attempts` keeps track of how many times the user has typed in a PIN. The variable `success` is set to either `True` or `False` based on whether the user is successful in signing in.

``````attempts = 0

while True:
attempts += 1

if code == "1234":
success = True
break

if attempts == 3:
success = False
break

# this is printed if the code was incorrect AND there have been less than three attempts
print("Incorrect...try again")

if success:
print("Correct PIN entered!")
else:
print("Too many attempts...")``````
Sample output

Sample output

The loop is exited either when the user types the correct PIN or if there have been too many attempts. The `if` statement after the loop checks the value of the variable `success` and prints out a message accordingly.

## Debugging print statements in loops

Adding loops to programs also adds to the potential sources of bugs. It becomes even more important to master the use of debugging print statements as introduced in the first section of this part.

Let's have a look at a program almost identical to the previous example, but with one crucial difference:

``````attempts = 0

while True:
attempts += 1

if attempts == 3:
success = False
break

if code == "1234":
success = True
break

print("Incorrect...try again")

if success:
print("Correct PIN entered!")
else:
print("Too many attempts...")``````

This version acts strangely when the user types in the correct code on the third attempt:

Sample output

So, let's try and find the cause by adding some strategic debugging print statements inside the loop:

``````while True:
print("beginning of the while block:")
attempts += 1

print("attempts:", attempts)
print("condition1:", attempts == 3)
if attempts == 3:
success = False
break

print("code:", code)
print("condition2:", code == "1234")
if code == "1234":
success = True
break

print("Incorrect...try again")``````
Sample output

beginning of the while block: Please type in your PIN: 2233 attempts: 1 condition1: False code: 2233 condition2: False Incorrect...try again beginning of the while block: Please type in your PIN: 4545 attempts: 2 condition1: False code: 4545 condition2: False Incorrect...try again beginning of the while block: Please type in your PIN: 1234 attempts: 3 condition1: True Too many attempts...

From the above printouts we can see that during the third iteration of the loop the condition of the first `if` statement is `True`, and the loop is exited. This iteration never gets to the second `if` statement, which checks whether the code was typed in correctly:

``````  while True:
# ....

# this block is executed too early
if attempts == 3:
success = False
break

# the third iteration never gets this far
if code == "1234":
success = True
break``````

The order of conditional statements, or of different branches within a conditional statement, is a common cause for bugs, especially in loops. Debugging print statements are often the simplest way of finding their cause.

## Concatenating strings with the + operator

The above example with PIN checking used a helper variable `attempts` to keep track of how many times the user had tried to type in a code:

``````attempts = 0

while True:
attempts += 1
# ...``````

The variable is set to zero outside the loop, and each iteration increases its value by one.

A similar idea of incrementation works with string variables as well. The program could, for instance, keep track of all the PIN codes the user typed in:

``````
codes = ""
attempts = 0

while True:
attempts += 1
codes += code + ", "
# ...``````

The helper variable is initialized to an empty string, that is, a string with no characters in it:

``codes = ""``

With each iteration the string gets longer, as the code the user typed in is added, along with a comma:

``````    code = input("Please type in your PIN: ")
codes += code + ", "``````

If the user types in the codes 1111 2222 1234, at the end of the program's execution the value of `codes` would be

Sample output

1111, 2222, 1234,

Please respond to a quick questionnaire on this week's materials.

: