9.3. Syntax Loop Else

  • Not only if statement has else clause

  • Conditionals: if ... elif ... else

  • Exceptions: try ... except ... else

  • While loop: while ... else

  • For loop: for ... else

>>> colors = ['red', 'green', 'blue']
>>> search = 'black'
>>>
>>> i = 0
>>> while i < len(colors):
...     color = colors[i]
...     i += 1
...     if color == search:
...         print('found')
...         break
... else:
...     print('missing')
...
missing
>>> colors = ['red', 'green', 'blue']
>>> search = 'black'
>>>
>>> for color in colors:
...     if color == search:
...         print('found')
...         break
... else:
...     print('missing')
...
missing

9.3.1. Example

  • 3, 2, 1, 0, Launching rocket to outer space

  • 3, 2, Fuel leak detected. Abort, Abort, Abort!

  • Note, this will print the value first, decrement and then check for leak

>>> i = 3
>>>
>>> while i >= 0:
...     print(i)
...     i -= 1
...
...     if i == None:  # no problems detected
...         print('Fuel leak detected. Abort, Abort, Abort!')
...         break
3
2
1
0
>>>
>>> print('Launching rocket to outer space')
Launching rocket to outer space
  • Can we launch a rocket?

>>> i = 3
>>>
>>> while i >= 0:
...     print(i)
...     i -= 1
...
...     if i == 1:  # problem detected in the last second
...         print('Fuel leak detected. Abort, Abort, Abort!')
...         break
3
2
Fuel leak detected. Abort, Abort, Abort!
>>>
>>> print('Launching rocket to outer space')
Launching rocket to outer space
  • This time we aborted and still launched - this is not good

  • How to detect if the countdown was successful?

9.3.2. Flag

In order to answer those questions we need to introduce a variable to hold the status if the countdown was aborted or successful. Let's name it abort. If the flag is set to True, then there was an abort procedure called during the countdown and we cannot launch a rocket to outer space.

>>> abort = False
>>> i = 3
>>>
>>> while i >= 0:
...     print(i)
...     i -= 1
...
...     if i == 1:  # problem detected in the last second
...         print('Fuel leak detected. Abort, Abort, Abort!')
...         abort = True
...         break
3
2
Fuel leak detected. Abort, Abort, Abort!
>>>
>>> if not abort:
...     print('Launching rocket to outer space')

But the problem here is that the follow-up code is split from the while loop. This can cause problems if the codebase will grow.

9.3.3. Else

The else clause to while loop will be executed if a loop does not exit with break statement. In the other words: if there was no problem detected during the countdown, launch the rocket to outer space.

>>> i = 3
>>>
>>> while i >= 0:
...     print(i)
...     i -= 1
...
...     if i == 1:  # problem detected in the last second
...         print('Fuel leak detected. Abort, Abort, Abort!')
...         break
... else:
...     print('Launching rocket to outer space')
3
2
Fuel leak detected. Abort, Abort, Abort!
>>> i = 3
>>>
>>> while i >= 0:
...     print(i)
...     i -= 1
...
...     if i == None:  # no problems detected
...         print('Fuel leak detected. Abort, Abort, Abort!')
...         break
... else:
...     print('Launching rocket to outer space')
3
2
1
0
Launching rocket to outer space

9.3.4. Assignments

Code 9.21. Solution
"""
* Assignment: Loop WhileElse Found
* Type: homework
* Complexity: medium
* Lines of code: 5 lines
* Time: 5 min

English:
    1. Modify game code below
    2. User can try `MAX_TRIES` times, if he/sh does not guess number by then
       print `Game over, max tries achieved.`
    3. Don't use `while ... else` syntax
    4. Run doctests - all must succeed

Polish:
    1. Zmodyfikuj kod gry poniżej
    2. Użytkownik może próbować `MAX_TRIES` razy, jeżeli w tym czasie nie zgadnie
       to wypisz `Game over, max tries achieved.`
    3. Nie używaj składni `while ... else`
    4. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `Stop` or `Ctrl+C` kills infinite loop

Tests:
    >>> import sys; sys.tracebacklimit = 0
"""


# Simulate user input (for test automation)
from unittest.mock import MagicMock
input = MagicMock(side_effect=['0', '9', '1', '8', '2', '7', '3', '6', '4'])


HIDDEN = 4
MAX_TRIES = 4


while True:
    guess = input('\nType number: ')

    if int(guess) > HIDDEN:
        print('Above')
    elif int(guess) < HIDDEN:
        print('Below')
    else:
        print('Exactly')
        break


Code 9.22. Solution
"""
* Assignment: Loop WhileElse Found
* Type: homework
* Complexity: medium
* Lines of code: 5 lines
* Time: 5 min

English:
    1. Modify game code below
    2. User can try `MAX_TRIES` times, if he/sh does not guess number by then
       print `Game over, max tries achieved.`
    3. Don't use `while ... else` syntax
    4. Run doctests - all must succeed

Polish:
    1. Zmodyfikuj kod gry poniżej
    2. Użytkownik może próbować `MAX_TRIES` razy, jeżeli w tym czasie nie zgadnie
       to wypisz `Game over, max tries achieved.`
    3. Nie używaj składni `while ... else`
    4. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `Stop` or `Ctrl+C` kills infinite loop

Tests:
    >>> import sys; sys.tracebacklimit = 0
"""


# Simulate user input (for test automation)
from unittest.mock import MagicMock
input = MagicMock(side_effect=['0', '9', '1', '8', '2', '7', '3', '6', '4'])


HIDDEN = 4
MAX_TRIES = 4


while True:
    guess = input('\nType number: ')

    if int(guess) > HIDDEN:
        print('Above')
    elif int(guess) < HIDDEN:
        print('Below')
    else:
        print('Exactly')
        break