Introductory Programming in Python: Lesson 7
Flow Control: Conditional Loops

[Prev: Flow Control: Conditionals] [Course Outline] [Next: Flow Control: Sequential Loops]

The while Statement

The last program we wrote, to count the number of even and negative numbers entered by the user, was already getting pretty large if one measures program size in lines of code. And it only handled three inputs! What if we wanted a hundred inputs. Cutting and pasting would work, but making those small changes to each section of code dealing with a specific number would be tedious at best, and error prone at worst. Fortunately, computers excel at repetitive tasks. Small things amuse small minds, I suppose. Enter the while statement.

The while statement executes a statement, or block of statements, repeatedly, as long as a given expression is True. So let's rethink out previous problem. Formerly we would have described the problem so

The user enters three integers. The program outputs how many of those integers were even, and how many were both even and negative. Also, if the number entered is even, a message stating the number entered is even is printed. Similarly a message is printed if the number is both even and negative, indicating the number is negative.

But we are not happy with just three numbers, so let's re-describe the behaviour we want from our program

The user may enter a number. Until the user enters a blank line, the program continues accepting numbers. After a blank line has been entered the program outputs the number of numbers entered by the user which were even, as well as the number of numbers which were both even and negative.

Much like how in junior school we were taught to look for key words in word problems to help us formulate the problem mathematically, we can and should do the same with descriptions of problems and their translation into program code. Everything in programming comes down to one of three 'structures'...

In the problem description above, we can identify some key words already hint at the structures we should use.

enter
Relates to input -- raw_input()
until
Indicates repetition based on the fulfillment of a condition -- while statement
output
Indicates output -- print statement
which
Indicates a condition without repetition -- if statement
both ... and ...
Indicates a composition of conditions -- and operator

We'll now step through the problem description, sentence by sentence and convert it into a python program, using the keywords as hints, and the tools we have already come across. Also we'll introduce the syntax of the while statement.

The user may enter a number.

Looking at the keywords and their hints, we want to use the raw_input here. This is true of any input from the keyboard generally. Thus, our first line of code will be

number = raw_input("Enter a number: ")
Until the user enters a blank line, the program continues accepting numbers.

Okay, from the hints we see we should be using a while statement, but beware! We don't have an 'until statement' in python, and in English until and while are opposites, so we just need to transform the problem slightly so that we now have

While the user enters a line that is not blank, the program continues accepting numbers.

This translates directly into python code which we append to what we've already got to produce

number = raw_input("Enter a number: ")
while number != '':
    number = raw_input("Enter another number (or nothing to finish): ")

Note the prompt has changed to tell the user what to do to exit the program, namely enter a blank line rather than a number. Also note the format, or syntax, of the while statement.

while <expression>:
    statement
    statement
    ...

See how we indent statements we want executed repetitively and conditionally under the while statement, in the same way as we do with if statements. The while statement checks the expression, and if it is True, will execute those indented statements once, after which it will check the expression again, and execute the statements etc ... If the expression is ever False, execution of the program continues at the first unindented statement after the indented block.

There's a little to more to the while loop that pure syntax. Every loop needs three things; A start point, an end point, and a way to get from one point to another. More importantly there needs to be a relationship between these three things, in the form of a variable. The start point takes the form of assigning a value (the starting value) to a variable, which we'll call the counter. The while loop's condition specifies the stop point of the loop, by specifying a condition under which the loop should terminate in terms of the counter variable. Finally, the loop needs a way to get from start to finish in a stepwise manner, i.e. a way to take a single step. This means the value of the counter variable must change inside the repeated block of statements, otherwise value of the loop condition won't change, and the loop will repeat forever. Commonly, the statement that changes the counter variable's value is placed at the end of the repeated black of statements, because this mean it is changed immediately before the counter variable is checked in the loop condition again. This gives us the pattern:

counter = <start_value> #Initialise the counter
while <expression>: #<expression> specifies when the loop will stop in terms of counter
    statement
    statement
    ...
    counter = <new value of counter< #changes the value of counter
After a blank line has been entered the program outputs the number of numbers entered by the user which were even,

Now we haven't kept a record of the numbers entered so how can we tell how many were even? The solution is to keep a count as even numbers are entered. How do we store a value? Variables! We need to know how many numbers were even, indicating quantity, indicating a number, i.e. an integer. So let's create a new integer to use whilst counting, and call it 'even'. But to create a new variable we have to give it a value! What value can we give even, if we don't know how many even numbers the user will enter? Well we do know how many even numbers there are before the user has entered any numbers; there are 0 even numbers. So let's put an assignment statement to that effect into our program in the right place (before a number is entered).

even = 0
number = raw_input("Enter a number: ")
while number != '':
    number = raw_input("Enter another number (or nothing to finish): ")

Now at the end of our program we still have 0 even numbers, because we haven't changed the value of 'even'. We wish to count how many numbers that are entered are even, which means we need to increment (increase by one) every time an even number is entered. Firstly, how do we distinguish even numbers from odd? We use an if statement, because this is a condition. Secondly, where to we actually place the counting statements. Here's a suggestion

even = 0
number = raw_input("Enter a number: ")
while number != '':
    if int(number) % 2 == 0: #if number is even
        even = even + 1
    number = raw_input("Enter another number (or nothing to finish): ")

A few things about our two new lines deserve mention. Firstly, as we are already familiar with, raw_input() returns a string, so we need to type cast to an integer before we can test whether it is even. Then there's the condition itself. The definition of an even number is a number divisible exactly by 2, i.e. without remainder. The '%' operator returns the remainder of a division, and is thus perfectly suited to the job of testing whether a number is even or odd. If the remainder of the division is 0, the number is even. Also we have nested the if statement within the while statement, so it may be executed multiple times, one each time a number is entered, to test the number. We have put it before the raw_input function within the while statement because we don't want to test an empty string (blank line) for evenness in the case where the user has not entered a number and wishes to finish up. This way the while statement's expression tests whether the input is a blank line, before we convert to an integer and test for evenness.

as well as the number of numbers which were both even and negative.

The last piece of the problem description says we should also count how many of the input numbers are negative as well as even. And we need to put some output at the end once we've counted everything. Well, this is very similar to the previous segment, so let's recycle the idea and see what we get...

even = 0
negative = 0
number = raw_input("Enter a number: ")
while number != '':
    if int(number) % 2 == 0: #if number is even
        even = even + 1
        if int(number) < 0:
            negative = negative + 1
    number = raw_input("Enter another number (or nothing to finish): ")
print "There were ", even, "even numbers, of which", negative, "were also negative"

So we've included a new variable, 'negative', which counts the number of negative entries, but only if those entries are even. Why is this? We haven't specified int(number) % 2 == 0 and int(number) < 0. Instead we have nested the test for negativity inside the test for evenness. This means a number will only be tested, and thus potentially counted, for negativity if it has already been found to be even.

The break Statement

Looking at the while statement, it seems that once we're in a block of statements to be executed repeatedly, known as a loop, we can't get out of the loop except when the expression after 'while' (or loop condition) is False. Python provides us with a statement for breaking out of a loop, conveniently called break. Suppose we wanted our program for counting even numbers to end not only when a blank line was entered, but also if the user enters the string 'quit'. We could simply add two lines ...

even = 0
negative = 0
number = raw_input("Enter a number (or nothing or 'quit' to quit): ")
while number != '':
    if number == 'quit':
        break
    if int(number) % 2 == 0: #if number is even
        even = even + 1
        if int(number) < 0:
            negative = negative + 1
    number = raw_input("Enter another number (or nothing to finish): ")
print "There were ", even, "even numbers, of which", negative, "were also negative"

Again we check what the user has entered, and if it is the string 'quit', we break out of the loop, meaning execution continues at the print statement.

The continue Statement

If we wanted to get picky and consider 0 to not be even, we would have to modify our code so that it doesn't count a '0' entry as even or negative. We can't simply break out of the loop, because the user may want to enter more numbers after the '0'. We could enclose the entire test for evenness in an if statement that makes sure the number entered is not 0, but python provides us with a more elegant solution, the continue statement. The continue statement jumps the flow of execution immediately back to the loop condition, at which point normal loop execution flow resumes.

even = 0
negative = 0
number = raw_input("Enter a number (or nothing or 'quit' to quit): ")
while number != '':
    if number == 'quit':
        break
    if number == '0':
        number = raw_input("Enter another number (or nothing or 'quit' to quit): ")
        continue
    if int(number) % 2 == 0: #if number is even
        even = even + 1
        if int(number) < 0:
            negative = negative + 1
    number = raw_input("Enter another number (or nothing or 'quit' to quit): ")
print "There were ", even, "even numbers, of which", negative, "were also negative"

else Clauses in while loops

'while loop' statements may also have an else clause, which is executed when the loop terminates when the condition becomes False, but not when the loop is terminated by a break statement. A nice example of this can be found here.

while <expression>:
    <statement>
    [statement]
else:
    <statement>
    [statement]

Exercises

Given the code ...

i = 1
while i < 32:
    if 32%i == 0:
        print i, "is a factor of 32"
    else:
        print i, "is not a factor of 32"
  1. How many lines of output will the above code produce?
  2. What needs to be done to correct the program?
  3. Write a program that outputs the word 'repeat' 100 times, each on a line of its own.
  4. Write a program that prints the numbers from 1 to 10 on the screen, on a single line, ending with a new line.
  5. Write a program that asks the user for a number and then prints the numbers from 1 to the number they entered.
  6. Write a program that asks the user for a number and then prints the sum of numbers from 1 to the number they entered.
  7. Write a program that asks the user for two numbers and then prints the sum of numbers from the lowest number entered to the highest number entered.
  8. Write a program that asks the user for a nucleotide sequence in any case (including mixed case). Output the sequence in lower case, on a single line, without spaces.
  9. Write a program that asks the user to enter a sequence of numbers, ending with a blank line. Print out the smallest of those numbers.
  10. Write a program that asks the user to enter a sequence of numbers, ending with a blank line. Print out the average of those numbers.
  11. Write a program that asks the user for a list of names ending with a blank line. The program then outputs a neat list containing the following, each on their own line, labelled: The first name alphabetically. The last name alphabetically, the shortest name, and the longest name.
  12. Write a program that prints the numbers from 1 to 100, 10 per each line.
  13. Modify your solution to question 10 so that instead of printing the average and then terminating when a blank line is entered, it prints the average and then asks if the user wants to repeat the process. If the user answers 'y' the process is repeated, otherwise the program terminates.
  14. Write a program that asks the user to enter two different phrases, and a single letter. Count the number of occurrences of the inputed letter in each phrase and output the phrase with the most occurrences.
  15. Write a program that asks the user for a sequence of floats, ending in a blank line. The user is then allowed to give one of the following commands:
    • mean: prints the mean of the numbers
    • sum: prints the sum of the numbers
    • quit: exits the program
    If 'mean' or 'sum' are entered, the program responds and then waits for more input.
[Prev: Flow Control: Conditionals] [Course Outline] [Next: Flow Control: Sequential Loops]