Now that we've examined some basic built-in types, let's look at two important control flow structures which depend on conversions to the bool type: if-statements and while-loops.
Control flow: if-statements and while-loops
Conditional control flow: The if-statement
Conditional statements allow us to branch execution based on the value of an expression. The form of the statement is the if keyword, followed by an expression, terminated by a colon to introduce a new block. Let's try this at the REPL:
>>> if True:
Remembering to indent four spaces within the block, we add some code to be executed if the condition is True, followed by a blank line to terminate the block:
... print("It's true!")
...
It's true!
At this point the block will execute, because self-evidently the condition is True. Conversely, if the condition is False, the code in the block does not execute:
>>> if False:
... print("It's true!")
...
>>>
The expression used with the if-statement will be converted to a bool just as if the bool() constructor had been used, so:
>>> if bool("eggs"):
... print("Yes please!")
...
Yes please!
If the value is exactly equivalent to something, we then use the if command as follows:
>>> if "eggs":
... print("Yes please!")
...
Yes please!
Thanks to this useful shorthand, explicit conversion to bool using the bool constructor is rarely used in Python.
if...else
The if-statement supports an optional else clause which goes in a block introduced by the else keyword (followed by a colon) which is indented to the same level as the if keyword. Let's start by creating (but not finishing) an if-block:
>>> h = 42
>>> if h > 50:
... print("Greater than 50")
To start the else block in this case, we just omit the indentation after the three dots:
... else:
... print("50 or smaller")
...
50 or smaller
if...elif...else
For multiple conditions you might be tempted to do something like this:
>>> if h > 50:
... print("Greater than 50")
... else:
... if h < 20:
... print("Less than 20")
... else:
... print("Between 20 and 50")
...
Between 20 and 50
Whenever you find yourself with an else-block containing a nested if statement, like this, you should consider using Python's elif keyword which is a combined else-if.
As the Zen of Python reminds us, Flat is better than nested:
>>> if h > 50:
... print("Greater than 50")
... elif h < 20:
... print("Less than 20")
... else:
... print("Between 20 and 50")
...
Between 20 and 50
This version is altogether easier to read.
Conditional repetition: the while-loop
Python has two types of loop: for-loops and while-loops. We've already briefly encountered for-loops back when we introduced significant whitespace, and we'll return to them soon, but right now we'll cover while-loops.
The While-loops in Python are introduced by the while keyword, which is followed by a boolean expression. As with the condition for if-statements, the expression is implicitly converted to a boolean value as if it has been passed to the bool() constructor. The while statement is terminated by a colon because it introduces a new block.
Let's write a loop at the REPL which counts down from five to one. We'll initialize a counter variable called c to five, and keep looping until we reach zero. Another new language feature here is the use of an augmented-assignment operator, -=, to subtract one from the value of the counter on each iteration. Similar augmented assignment operators exist for the other basic math operations such as addition and multiplication:
>>> c = 5
>>> while c != 0:
... print(c)
... c -= 1
...
5
4
3
2
1
Because the condition — or predicate — will be implicitly converted to bool, just as if a call to the bool() constructor were present, we could replace the above code with the following version:
>>> c = 5
>>> while c:
... print(c)
... c -= 1
...
5
4
3
2
1
This works because the conversion of the integer value of c to bool results in True until we get to zero which converts to False. That said, to use this short form in this case might be described as un-Pythonic, because, referring back to the Zen of Python, explicit is better than implicit. We place higher value of the readability of the first form over the concision of the second form.
The While-loops are often used in Python where an infinite loop is required. We achieve this simply by passing True as the predicate expression to the while construct:
>>> while True:
... print("Looping!")
...
Looping!
Looping!
Looping!
Looping!
Looping!
Looping!
Looping!
Looping!
Now you're probably wondering how we get out of this loop and regain control of our REPL! Simply press Ctrl+C:
Looping!
Looping!
Looping!
Looping!
Looping!
Looping!^C
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
KeyboardInterrupt
>>>
Python intercepts the key stroke and raises a special exception which terminates the loop. We'll be talking much more about what exceptions are, and how to use them, later in Chapter 6, Exceptions.
Exiting loops with break
Many programming languages support a loop construct which places the predicate test at the end of the loop rather than at the beginning. For example, C, C++, C# and Java support the do-while construct. Other languages have repeat-until loops instead or as well. This is not the case in Python, where the idiom is to use while True together with an early exit, facilitated by the break statement.
The break statement jumps out of the loop — and only the innermost loop if severals loops have been nested — continuing execution immediately after the loop body.
Let's look at an example of break, introducing a few other Python features along the way, and examine it line-by-line:
>>> while True:
... response = input()
... if int(response) % 7 == 0:
... break
...
We start with a while True: for an infinite loop. On the first statement of the while block we use the built-in input() function to request a string from the user. We assign that string to a variable called response.
We now use an if-statement to test whether the value provided is divisible by seven. We convert the response string to an integer using the int() constructor and then use the modulus operator, %, to divide by seven and give the remainder. If the remainder is equal to zero, the response was divisible by seven, and we enter the body of the if-block.
Within the if-block, now two levels of indentation deep, we start with eight spaces and use the break keyword. break terminates the inner-most loop — in this case the while-loop — and causes execution to jump to the first statement after the loop.
Here, that statement is the end of the program. We enter a blank line at the three dots prompt to close both the if-block and the while-block. Our loop will start executing, and will pause at the call to input() waiting for us to enter a number. Let's try a few:
12
67
34
28
>>>
As soon as we enter a number divisible by seven the predicate becomes True, we enter the if-block, and then we literally break out of the loop to the end of program, returning us to the REPL prompt.