Jump to content

Python Concepts/While Statement

From Wikiversity

Objective

[edit | edit source]
  • Learn about Python's loop statement, while.
  • Learn about three dependent statements, else, break, and continue.

Lesson

[edit | edit source]

The While Statement

[edit | edit source]

Although the if statement from the previous lesson can serve many purposes, it isn't good at being recursive. This means that the said statement cannot loop over and over again. This is where the while statement comes into play. This statement will execute its code block over and over again until its conditions are false. This can be useful if something needs to be repeated over and over for a said amount of time. Some examples are given below.

>>> pop = 0
>>> while pop != 5:
...     pop += 1
...     print(pop)
...
1
2
3
4
5
>>> eggs = [12, 4, 2, 6, 11, 23]
>>> while eggs:
...     print(eggs[0])
...     del eggs[0]
...
12
4
2
6
11
23
>>> while False:
...     print("This will never print!")
...
>>> spam = 10
>>> while spam:
...     spam -= 1
...     print(spam)
...
9
8
7
6
5
4
3
2
1
0


A while statement's condition is always true or false, like the if statement. This means Boolean math can be used to control the looping. Since while False: will never execute, what will while True: do? It will infinitely loop. This will be important later; we'll spend more time on it later in the lesson.

The Else Statement

[edit | edit source]

Unlike a lot of other computer languages, Python allows you to use an else statement in conjunction with a while statement. When a while statement finishes its loop naturally, it will then execute the else statement. If the while statement stops prematurely for any reason, it will not execute the else statement. An example is given below.

>>> spam = 0
>>> while spam != 10:
...     spam += 1
...     print(spam)
... else:
...     print("Done printing spam!")
...
1
2
3
4
5
6
7
8
9
10
Done printing spam!
>>> while True:
...     pass
... else:
...     print("I'll never get seen on the screen!")
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyboardInterrupt


In the second example, ctrl+c is used to generate a KeyboardInterrupt. Because the while statement ended prematurely, the else statement was never executed.

The Break Statement

[edit | edit source]

There can be times when you want to prematurely end a while statement. The break statement can be used to accomplish this. The break statement can be used to prematurely end the while statement that it's nested in. This means it will end only one while statement, not all of them. An example is given below.

>>> pop = 0
>>> while True:
...     print(pop)
...     pop += 1
...     if pop == 10:
...         break
...
0
1
2
3
4
5
6
7
8
9


The above example demonstrates that a while loop can be ended, even if it is True. You should also note from the example that the break statement doesn't require a colon (:), which means new indentation isn't needed. Putting a colon at the end of break will cause an error; the omission of the colon isn't optional, it's mandatory.

Continue Statement

[edit | edit source]

Although the break statement comes in handy, the continue statement is just as useful. Unlike the break statement, the continue statement will stop the current execution of code and go back to the beginning of the while statement. This can be used to skip part of the code and not end the loop at the same time. The continue statement is used just like the break statement. An example is given below.

>>> bacon = 0
>>> while bacon != 10:
...     bacon += 1
...     if bacon < 5:
...         continue
...     print(bacon)
...
5
6
7
8
9
10


Although the example could have easily omitted the continue, it demonstrates how it works. The continue statement is used to reduce the amount of indenting and nesting used; it would be easier to check five conditions and use a continue if they fail, than to nest five if statements. This can reduce the amount of typing needed and, as a result, will increase readability and code clarity.

Detecting Abnormal Termination

[edit | edit source]

If the while statement terminates normally, the else statement is executed:

x = 11 ; normalTermination = False
while x :
    x -= 1
    if x < 5 : continue
    print (x)
else :
    normalTermination = True

if normalTermination :
    print ('normal termination')
else:
    print ('abnormal termination')
10

9

8

7

6

5

normal termination


If the while statement terminates abnormally, the else statement is not executed. The following code detects abnormal termination:

x = 11 ; normalTermination = False
while x :
    x -= 1
    if x < 5 : break
    print (x)
else :
    normalTermination = True

if normalTermination :
    print ('normal termination')
else:
    print ('abnormal termination')
10

9

8

7

6

5

abnormal termination

"Normal" termination

[edit | edit source]

The following code produces four examples of "Normal" termination:

for c in [-4,0,3,19] :
    print ('\ninitial c =', c)
    while  5 > c >= 0  :
        print ('c =', c)
        c += 1
    else :
        print ('normal termination. c =', c)
initial c = -4

normal termination. c = -4


initial c = 0

c = 0

c = 1

c = 2

c = 3

c = 4

normal termination. c = 5 # This is probably what you wanted.


initial c = 3

c = 3

c = 4

normal termination. c = 5


initial c = 19

normal termination. c = 19

The following code also produces "Normal" termination:

c = 0
print ('\ninitial c =', c)
while  5 > c >= 0  :
    print ('c =', c)
    c += 1
    if c == 4 : c += 234 # to simulate c becoming corrupted                                                           
else :
    print ('normal termination. c =', c)
initial c = 0

c = 0

c = 1

c = 2

c = 3

normal termination. c = 238

For normal termination we expect c to have the value 5. Try again:

for c in [-4,0,3,19] :
    print ('\ninitial c =', c)
    while  5 > c >= 0  :
        print ('c =', c)
        c += 1
    else :
        if c == 5 : print ('normal termination. c =', c)
initial c = -4


initial c = 0

c = 0

c = 1

c = 2

c = 3

c = 4

normal termination. c = 5


initial c = 3

c = 3

c = 4

normal termination. c = 5


initial c = 19

Even this code is not fool-proof. Try again:

for c in [-4,0,3,19] :
    print ('\ninitial c =', c)
    count = 0
    while  5 > c >= 0  :
        print ('c =', c)
        c += 1
        count += 1
    else :
        if c == count == 5 : print ('normal termination. c =', c)
initial c = -4


initial c = 0

c = 0

c = 1

c = 2

c = 3

c = 4

normal termination. c = 5


initial c = 3

c = 3

c = 4


initial c = 19

You can see that controlling the performance and behavior of loops is not a trivial matter.

The else statement

[edit | edit source]

It seems that the else statement in the next block:

while condition :
    pass
    pass ; etc
else :
    pass # normal termination

performs the same function as:

while condition :
    pass
    pass ; etc
if condition : pass
else :
    pass # normal termination

For example:

while 5 > c >= 0 :
    pass
    pass ; etc
if 5 > c >= 0 : pass
else :
    pass # normal termination

and

while 5 > c >= 0 :
    pass
    pass ; etc
else :
    pass # normal termination

have the same functionality.

Nested while statements

[edit | edit source]

while statements are nested when the body of one while statement contains another while statement:

a = 0
while a < 10 :
    b = 0
    while b < 10 :
        c = 0
        while c < 10 :
            print ('{}{}{}'.format(a,b,c))
            pass
            c += 1
        b += 1
    a += 1
else:
    print ('normal termination')
000 #

001 #

... # 1000 numbers from 000 through 999

998 #

999 #

normal termination

In the body of the innermost while statement above there is a pass statement. What if there were at this point a condition that required the immediate termination of all while statements? Here is one way to do it:

a = 0 ; flag = True
while a < 10 and flag :
    b = 0
    while b < 10 and flag :
        c = 0
        while c < 10 :
            print ('{}{}{}'.format(a,b,c))
            if a ==2 and b == 4 and c == 3 : flag = False ; break
            c += 1
        b += 1
    a += 1
else:
    print ('normal termination')

print ('flag =', flag)
000 #

001 #

... # 244 numbers from 000 through 243

242 #

243 #

normal termination

flag = False # This indicates abnormal termination.


Python's ability to handle errors adds some elegance to the solution:

class label(Exception): pass  # declare a label                                                                      

try:
    a = 0
    while a < 10 :
        b = 0
        while b < 10 :
            c = 0
            while c < 10 :
                print ('{}{}{}'.format(a,b,c))
#                if a ==2 and b == 4 and c == 3  : raise label()  # goto label                                       
#                if a ==2 and b == 4 and c == 3  : raise KeyError                                                    
                if a ==2 and b == 4 and c == 3  : 1/0  # force an error, divide by 0.
                c += 1
            b += 1
        a += 1
    else:
        print ('normal termination')
except label:  # where to goto                                                                                       
    print ('took exception')
except ZeroDivisionError :
    print ('ZeroDivisionError')
except ValueError :
    pass
except KeyError :
    print ('KeyError')
except :
    print ('unknown')
000

001

002

....

241

242

243

ZeroDivisionError

The try statement will be presented in a later lesson.

Programming style

[edit | edit source]

Avoid hidden endless loops such as:

a = 2
while a != 9 :
    pass
    a += 2

or

a = 2
while a < 30 :
    pass
    a += b # what if b is always negative?

or

a = 2
while a < 30 :
    if a > 20 : continue
    pass
    a += 1

Avoid loops that will never iterate:

a = 2
while (a % 5) == 3 :
    pass
    a += 1
else :
    print ('Normal termination.')

In some of the examples above the incrementer was at the bottom of the loop:

c = 0
while c < 10 :
    print ('c =', c)
    pass
    pass
    pass
    c += 1

As the body of the loop gets bigger, the importance of the incrementer remains but becomes less obvious. The following code with the incrementer at the top does the same job:

c = -1
while c + 1 < 10 :
    c += 1
    print ('c =', c)
    pass
    pass
    pass

With the incrementer at the top you can put more code into the body of the loop without having to consider the incrementer.


For rigorous control of the loop you might consider:

c = 0
pass
pass
if c == 0 :
    while c < 5 :
        print ('c =', c)
        pass # Be careful not to call a function here that might change 'c'.
        c += 1
    else :
        if c == 5 : # This is a necessary (but insufficient) test for normal termination of this loop.
            print ('Normal termination') # "Normal termination" means normal termination of the loop.
                                         # It does not mean normal termination of the job.
else :
    print ('initial value of c', c, 'not acceptable for this loop.')
c = 0

c = 1

c = 2

c = 3

c = 4

Normal termination

Examples

[edit | edit source]

Given a = [0,1,-2,3,-4,-5,-6,-7,8,-9,10,11,-12], remove all negative values from list a.

p = 0
while p < len(a):
    if a[p] < 0 : del a[p]
    p += 1

print ('a =', a)

a = [0, 1, 3, -5, -7, 8, 10, 11]

Take care when code in the body of the loop changes a condition of the loop. Reverse the order of test and delete, and you can ignore whatever may have happened behind you:

a = [0,1,-2,3,-4,-5,-6,-7,8,-9,10,11,-12]

p = len(a) - 1

while p >= 0 :
    if a[p] < 0 : del a[p]
    p -= 1

print ('a =', a)

a = [0, 1, 3, 8, 10, 11]


The simple equivalent of a 'case' statement:

conditionFound = True
while True :
    if a == condition1 :
        pass; pass; etc
        break
    if a == condition2 :
        pass; pass; etc
        break
    if a == condition3 :
        pass; pass; etc
        break
    conditionFound = False ; break

Assignments

[edit | edit source]
  • Work with the while statement and get a general feeling of how it works.
  • PEP 315 proposed that an optional do clause should be added to the while statement, although it was ultimately rejected. Read PEP 315. Why do you think it was rejected? How would this affect readability?

Further Reading or Review

[edit | edit source]
Completion status: Ready for testing by learners and teachers. Please begin!

References

[edit | edit source]

1. Python's documentation:

"3.2. First Steps Towards Programming", "4.4. break and continue Statements, and else Clauses on Loops", "5.6. Looping Techniques", "7.9. The break statement", "7.10. The continue statement", "8.2. The while statement"


2. Python's methods:


3. Python's built-in functions: