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.
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.
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.
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"
'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]
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"