While Loops (Iteration)

Introduction to Software Engineering (CSSE 1001)

Author

Paul Vrbik

Published

March 13, 2025

There are (at least) two scenarios where repeating possibly indefinitely, is necessary:

  1. prompting the user for valid input, and
  2. playing a random game (i.e. guessing dice rolls).

While and Do Loops

A loop is a control structure that repeats code that belongs to it.

A while-loop is a control structure that repeats code while some condition is satisfied.

Figure 1: Flow-chart for while-loop. Notice we have an arrow that goes “up” now.

While-Loop

while <condition>:
    <code>
x = 0
while x < 10:
    x = x + 1  # Accumulator
x
10

Python Assignment Operators

Because accumulators like this or so common, there are some syntactic shortcuts we can use.

  1. x += y is equivalent to x = x + y
  2. x *= y is equivalent to x = x * y
  3. x /= y is equivalent to x = x / y
  4. x %= y is equivalent to x = x % y
x = 0
while x < 10:
    x += 1  # Accumulator
x
10

Infinite Loops

x = 0
while True:
    print(x)
    x += 1 
0
1
2
3
.
.
. (infinite)

There is usually a key-stroke, typically Ctrl+C, that terminates a loop — it is a good idea to learn what it is in your IDE!

x = 0
while False:
    print(x)
    x += 1 

Nothing prints.

The break keyword terminates a loop immediately and continues.

while True:
    print("hello")
    break
    print("world") 
hello

Do-While-Loop

A do-while or repeat-until are while-loop variants available in other languages.

There is a popular variant to the while-loop called a do-while or repeat-until that executes its body at least once.

do:
    <code>
while <condition>  # this is not valid Python syntax

Although not natively supported in Python (they are in many other languages), we can simulate them.

x = 0
while 1:  # Some programmers prefer 1 to True
    x += 1
    if x > 0:
        break

Big Example: Rebuilding Arithmetic

Suppose we have access to a succ (successor) and pred (predecessor) function that increments or decrements a value by one.

succ(1)
2
succ(2)
3
pred(1)
0
pred(2)
1

Can we implement addition, multiplication, and power using only these functions?

Our task will work as follows. We will assume there are values loaded in x and y and will have completed the task if ultimately the correct value to z is assigned. We will also restrict our task to arithmetic on postive numbers only.

Suffice to say that we are disallowed from using any of the built-in arithmetic (e.g. +, *, …) to complete this task.

Task 1 (Addition)

The following code sequence increments x by one y-many times. This is equivalent to incrementing x by y. Which is further equivalent to adding x and y.

# Stores the sum of x and y in z.
x, y = 2, 3

while y:  # the "Pythonic" way of checking y != 0
    x = succ(x) # +1 to x
    y = pred(y) # -1 to y

z = x
# z is now x + y
z
5

Task 2 (Multiplication)

This code sequence accumulates on t by r-increments s-many times. This is equivalent to multiplying r by s.

# Stores the PRODUCT of r and s in t.
r, s = 2, 3
t = 0

while s:
    t = t + r    # we were not allowed to use this
    s = pred(s)
# t is now r * s
t
6

We “refactor” our code to use our definition of addition.

# stores the PRODUCT of r and s in t.
r, s = 2, 7
t = 0
while s:
    # Stores the sum of x and y in z.
    x, y = t, r
    while y:
        x = succ(x)
        y = pred(y)
    z = x
    # z is now x + y
    t = z
    s = pred(s)
# t is now r * s
t
14

Task 3 (Power)

# stores the POWER of and a and b in c
a, b = 2, 7
c = 1

while b:
    c = c * a   # we weren't allowed to do this
    b = pred(b)
# c is now a**b
c
128

Refactoring to use our own multiplication code.

# stores the POWER of and a and b in c
a, b = 2, 7
c = 1

while b:
    # stores the PRODUCT of r and s in t.
    r, s = c, a
    t = 0
    while s:
        # Stores the sum of x and y in z.
        x, y = t, r
        while y:
            x = succ(x)
            y = pred(y)
        z = x
        # z is now x + y
        t = z
        s = pred(s)
    # t is now r * s
    c = t
    b = pred(b)
# c is now a**b
c
128

Refactoring with Functions

As we can see our listings are getting somewhat cumbersome. This is precisely where functions should be utilized to abstract our code into more manageable pieces.

Our addition code, for example,

# Stores the sum of x and y in z.
x, y = 2, 3

while y:  # the "Pythonic" way of checking y != 0
    x = succ(x)
    y = pred(y)

z = x
# z is now x + y

is better implemented by the add function.

def add_positive(x: int, y: int) -> int:
    """Return the sum of x and y.

    Precondition:
        x > 0
        y > 0

    >>> add_positive(2, 3)
    5
    """
    while y:  # the "Pythonic" way of checking y != 0
        x = succ(x)
        y = pred(y)
    
    return x



















Assigning z = x and returning z is the same thing as just returning x.

add_positive(2, 3)
5


We can contrast and compare the behaviour of code sequence against its implementation as a function. Note that because succ and pred do not actually exist in Python, we had to use arithmetic for this example.


This simplification cascades down into multiplication and power.

def multiply_positive(r: int, s: int) -> int:
    """Return the product of r and s.

    Precondition:
        r > 0
        s > 0

    >>> multiply_positive(2, 3)
    6
    """
    t = 0

    while s:
        t = add_positive(t, r)
        s = pred(s)
    
    return t
add_positive(2, 3)
5
def power_positive(a: int, b: int) -> int:
    """Return a to the power of b.

    Precondition:
        a > 0
        b > 0

    >>> power_positive(2, 3)
    8
    """
    c = 1

    while b:
        c = multiply_positive(c, a)
        b = pred(b)
    
    return c
power_positive(2, 7)
128

Exercise 1 Using only the new arithmetic functions we have developed. Implement

greater_than(x: int, y: int) -> int

which is true only when x > z. Do not use >.

User Input

The command x = input() will wait for input from the keyboard and then assign it to x with type(x) is str.

Exercise 2 Write a function foo(target: int) -> int that prompts the user to input a number until the user guesses some (secret) target.

For each guess the function should print Too high, Too low, or That's it! depending on the guess.

Return the number of guesses required.

def foo(target: int) -> int:
    number_of_guesses = 0
    while True:
        guess = int(input("Guess: "))
        number_of_guesses += 1
        if guess > target:
            print("Too high")
        elif guess < target:
            print("Too low")
        else:
            print("That's it!")
            return number_of_guesses

Random Numbers

Random number generation is handled by an external library. It is not built-in and therefore must be imported.

We can “import” a single command from the random library as follows.

from random import randint
randint(1,6)  # Chosen uniformly over the interval.
4

Or we can import every command (which is almost certainly a bad idea because this pollutes our name space by defining a bunch of names “behind our backs”).

import random
random.randint(1,6)
1

Exercise 3 Write a function called bar() -> Nothing that prompts the user to predict the result of a six-sided dice roll.

Repeat the prompt until the user predicts correctly.

from random import randint
def bar() -> None:
    """
    Prompt user to predict the result of a six sided dice roll until the 
    guess is correct.
    """
    while True:
        guess = int(input("Guess in [1..6]: "))
        roll  = randint(1, 6)
        if roll == guess:
            break
    return

Exercise 4 Write a function that prints the result of a six-sided dice roll until a six is rolled. Return the number of rolls required.

Exercise 5 Write a function that accumulates the result of dice rolls until some threshold is met/passed. Return the number of rolls required.

Summary

The while-loop is a control structure for repeating code a possibly infinite number of times.

Further Resources