forked from ninas/umonya_notes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
while_loops.html
464 lines (371 loc) · 18.1 KB
/
while_loops.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Introductory Programming in Python: Flow Control Conditional Loops</title>
<link rel='stylesheet' type='text/css' href='style.css' />
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
<script src="animation.js" type="text/javascript">
</script>
</head>
<body onload="animate_loop()">
<div class="page">
<h1>Introductory Programming in Python: Lesson 7<br />
Flow Control: Conditional Loops</h1>
<div class="centered">
[<a href="conditionals.html">Prev: Flow Control: Conditionals</a>] [<a href="index.html">Course Outline</a>] [<a href="lists.html">Next: Lists</a>]
</div>
<h2>The while Statement</h2>
<p>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 <a class="doclink"
href="http://olympiad.cs.uct.ac.za/docs/python-docs-2.6/reference/compound_stmts.html#while">while statement</a>.</p>
<p>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</p>
<blockquote class='problem'>
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.
</blockquote>
<p>But we are not happy with just three numbers, so let's re-describe
the behaviour we want from our program</p>
<blockquote class='problem'>
The user may <strong>enter</strong> a number.
<strong>Until</strong> the user enters a blank line, the program
continues accepting numbers. After a blank line has been entered
the program <strong>outputs</strong> the number of numbers entered
by the user <strong>which</strong> were even, as well as the number
of numbers <strong>which</strong> were <span
class='group'><strong>both</strong> even <strong>and</strong>
negative</span>.
</blockquote>
<p>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'...</p>
<ul>
<li>A sequence of steps</li>
<li>A condition that selects which sequence of steps to
execute</li>
<li>A repetition of a sequence of steps</li>
</ul>
<p>In the problem description above, we can identify some key words
already hint at the structures we should use.</p>
<dl>
<dt>enter</dt>
<dd>Relates to input -- raw_input()</dd>
<dt>until</dt>
<dd>Indicates <strong>repetition</strong> based on the fulfillment
of a <strong>condition</strong> -- while statement</dd>
<dt>output</dt>
<dd>Indicates <strong>output</strong> -- print statement</dd>
<dt>which</dt>
<dd>Indicates a <strong>condition without repetition</strong> -- if
statement</dd>
<dt>both ... and ...</dt>
<dd>Indicates a <strong>composition of conditions</strong> -- and
operator</dd>
</dl>
<p>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.</p>
<blockquote class='problem'>
The user may enter a number.
</blockquote>
<p>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</p>
<pre class='listing'>
number = raw_input("Enter a number: ")
</pre>
<blockquote class='problem'>
Until the user enters a blank line, the program continues accepting numbers.
</blockquote>
<p>Okay, from the hints we see we should be using a while statement,
but <strong>beware</strong>! 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</p>
<blockquote class='problem'>
<strong>While</strong> the user enters a line <strong>that is not
blank</strong>, the program continues accepting numbers.
</blockquote>
<p>This translates directly into python code which we append to what
we've already got to produce</p>
<pre class='listing'>
number = raw_input("Enter a number: ")
while number != '':
number = raw_input("Enter another number (or nothing to finish): ")
</pre>
<p>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.</p>
<pre class='definition'>
while <expression>:
statement
statement
...
</pre>
<p>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.</p>
<p>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 <strong>in terms of the counter
variable</strong>. 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
<strong>inside</strong> 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 <em>end</em> 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:</p>
<pre class='definition'>
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
</pre>
<blockquote class='problem'>
After a blank line has been entered the program outputs the number
of numbers entered by the user which were even,
</blockquote>
<p>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?
<strong>Variables</strong>! We need to know <strong>how many</strong>
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).</p>
<pre class='listing'>
even = 0
number = raw_input("Enter a number: ")
while number != '':
number = raw_input("Enter another number (or nothing to finish): ")
</pre>
<p>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</p>
<pre class='listing'>
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): ")
</pre>
<p>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 <strong>before</strong> 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.</p>
<blockquote class='problem'>
as well as the number of numbers which were both even and negative.
</blockquote>
<p>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...</p>
<pre class='listing'>
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"
</pre>
<p>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 <code>int(number) % 2 == 0 and int(number)
< 0</code>. 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.</p>
<h2>The break Statement</h2>
<p>Looking at the while statement, it seems that once we're in a block
of statements to be executed repeatedly, known as a
<strong>loop</strong>, we can't get out of the loop except when the
expression after 'while' (or <strong>loop condition</strong>) is False.
Python provides us with a statement for breaking out of a loop,
conveniently called <a class="doclink"
href="http://olympiad.cs.uct.ac.za/docs/python-docs-2.6/reference/simple_stmts.html#break">break</a>. 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 ...</p>
<pre class='listing'>
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"
</pre>
<p>Again we check what the user has entered, and if it is the string
'quit', we <strong>break</strong> out of the loop, meaning execution
continues at the print statement.</p>
<h2>The continue Statement</h2>
<p>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 <a
class="doclink"
href="http://olympiad.cs.uct.ac.za/docs/python-docs-2.6/reference/simple_stmts.html#continue">continue statement</a>.
The continue statement jumps the flow of execution immediately back to
the loop condition, at which point normal loop execution flow
resumes.</p>
<pre class='listing'>
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"
</pre>
<h2>else Clauses in while loops</h2>
<p>'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 <a class="doclink"
href='http://olympiad.cs.uct.ac.za/docs/python-docs-2.6/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops'>here</a>.</p>
<pre class='definition'>
while <expression>:
<statement>
[statement]
else:
<statement>
[statement]
</pre>
<h2>Exercises</h2>
<p>Given the code ...</p>
<pre class='listing'>
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"
</pre>
<ol>
<li>How many lines of output will the above code produce?</li>
<li>What needs to be done to correct the program?</li>
<li>Write a program that outputs the word 'repeat' 100 times,
each on a line of its own.</li>
<li>Write a program that prints the numbers from 1 to 10 on the
screen, on a single line, ending with a new line.</li>
<li>Write a program that asks the user for a number and then
prints the numbers from 1 to the number they entered.</li>
<li>Write a program that asks the user for a number and then
prints the sum of numbers from 1 to the number they
entered.</li>
<li>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.</li>
<!--<li>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.</li>-->
<li>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.</li>
<li>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.</li>
<!--<li>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.</li>-->
<li>Write a program that prints the numbers from 1 to 100, 10
per each line.</li>
<!--<li>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.</li>-->
<!--<li>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.</li>-->
<!--<li>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:<ul>
<li>mean: prints the mean of the numbers</li>
<li>sum: prints the sum of the numbers</li>
<li>quit: exits the program</li>
</ul>
If 'mean' or 'sum' are entered, the program responds and then
waits for more input.</li>-->
</ol>
<div class="centered">
[<a href="conditionals.html">Prev: Flow Control: Conditionals</a>] [<a href="index.html">Course Outline</a>] [<a href="lists.html">Next: Lists</a>]
</div>
</div>
<div class="pagefooter">
Copyright © James Dominy 2007-2008; Released under the <a href="http://www.gnu.org/copyleft/fdl.html">GNU Free Documentation License</a><br />
<a href="intropython.tar.gz">Download the tarball</a>
</div>
</body>
</html>