# Python Concepts/While Statement
## Objective

* Learn about Python's loop statement, while.
* Learn about three dependent statements, else, break, and continue.

## Lesson

* The While Statement
* 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
* 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
* 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
* 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

* 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
* 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
* 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

* 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

* 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

* 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

* 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

Completion status: Ready for testing by learners and teachers. Please begin!
Previous Lesson: Match-case Statement
This Lesson: While Statement
Next Lesson: For Statement
Course Home Page :