3
By the end of this chapter, you will be able to:
This lesson describes the Python program flow and how we can change the flow of execution using control statements such as if, while, for, and range.
Previously in this book, we covered the following topics:
In this chapter, we are going to build on the knowledge that we have acquired so far to dive deeper into the beautiful language that is Python. In this chapter, we will explore how Python handles control statements—in simple terms, how Python handles decision making, for instance, resulting to True if 2 + 3 = 5.
In this chapter, we will also dive deeper into program flow control. In particular, we will look at how we can run code repeatedly or in a loop.
Specifically, we will cover the following topics:
Like most programming languages, Python supports a number of ways to control the execution of a program by using control statements. Some of them might already be familiar, while others are unique to Python either in terms of syntax or execution.
In this chapter, we will delve into controlling program flow and start working on building more structured programs. This should also prepare us for learning various kinds of loops later in this chapter. To start us off, we are going to define some terms:
Program flow describes the way in which statements in code are executed. This also includes the priority given to different elements.
Python uses a simple top-down program flow. This is to say that code is executed in sequence from the top of the file to the very bottom. Each line has to wait until all of the lines that come before it have completed execution before their own execution can begin.
This top-down program flow makes it easy to understand and debug Python programs, as you can visually step through the code and see where things are failing.
In a top-down scenario, a problem is broken down into simple modules, each responsible for a part of the solution, closely related to one another. For instance, consider a salary calculation. There would be a module responsible for each of the following:
Having defined the program flow, we can now understand what a control statement is.
A control statement is a structure in code that conditionally changes the program flow. A control statement achieves this by conditionally executing different parts of code. A control statement can also be used to repeatedly and conditionally execute some code.
You can think of a control statement as a traffic police officer at a junction who only lets traffic through if the exit is clear. Checking whether the exit is clear would be the condition, in this case. The officer will only let cars through the junction when the exit is clear.
The two main control statements in Python are:
An if statement allows you to execute a block of code if a condition is true. Otherwise, it can run an alternative block of code in its else clause.
The else clause of an if statement is optional.
You can chain multiple if statements that check for multiple conditions one after the other and execute a different block of code when the various conditions are true.
The basic syntax of an if statement is shown here:
if condition:
# Run this code if the condition evaluates to True
else:
# Run this code if the condition evaluates to False
As you can see, the if statement allows you to branch the execution of code based on a condition. If the condition evaluates to true, we execute the code in the if block. If the condition evaluates to false, we execute the code in the else block.
In this exercise, we will see a practical application of the if statement:
release_year = '1991'
answer = input('When was Python first released?')
if answer == release_year:
print('Congratulations! That is correct.')
If the answer is greater than the correct answer, we tell the user that the guess was too high:
elif answer > release_year:
print('No, that's too late')
If the answer is less than the correct answer, we tell the user that the guess was too low:
elif answer < release_year:
print('No, that's too early')
print('Bye!')
The final code is as follows:
# Set release_year to 1991
release_year = '1991'
# Prompt the user to enter their answer to the question
answer = input('When was Python first released?')
if answer == release_year:
# If the answer is correct, show the success message
print('Congratulations! That is correct.')
elif answer > release_year:
# If the answer is greater that release_year, tell the user the guess was too high
print('No, that's too late')
elif answer < release_year:
# If the answer is less that release_year, tell the user the guess was too low
print('No, that's too early')
# Finally, print the exit message
print('Bye!')
Now let's look at some sample output from running this program and giving it various responses:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
When was Python first released? 1969
No, that's too early
Bye!
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
When was Python first released? 1991
Congratulations! That is correct.
Bye!
An if statement is used when you want to conditionally execute different blocks of code. The if statement is especially useful when there are multiple different blocks of code that could be executed, depending on multiple conditions.
We have recently walked through a simple if statement block that results to a value based on the input given. This is given here:
release_year = 1991
answer = input('When was Python first released?')
if answer == release_year:
print('Congratulations! That is correct.')
elif answer > release_year:
print('No, that's too late')
elif answer < release_year:
print('No, that's too early')
print('Bye!')
Modify this block as follows:
Create a script called if_python.py and add your code to it. Then, run it in a terminal. The output should be as follows:
>python if_python.py
Return TRUE or FALSE: Python was released in 1991:
TRUE
Correct
Bye!
>python if_python.py
Return TRUE or FALSE: Python was released in 1991:
FALSE
Wrong
Bye!
Solution for this activity can be found at page 283.
A while statement allows you to execute a block of code repeatedly, as long as a condition remains true. That is to say, as long as condition X remains true, execute this code.
A while statement can also have an else clause that will be executed exactly once when the condition, X, that's mentioned is no longer true. This can be read as follows: As long as X remains true, execute this block of code, else, execute this other block of code immediately so that the condition is no longer true.
For instance, consider the traffic police officer we mentioned earlier, who could be letting traffic through while the exit is clear, and as soon as it is not clear, they stop the drivers from exiting.
Here is the basic syntax of a while statement:
while condition:
# Run this code while condition is true
# Replace the "condition" above with an actual condition
# This code keeps running as long as the condition evaluates to True
else:
# Run the code in here once the condition is no longer true
# This code only runs one time unlike the code in the while block
As mentioned earlier, this can be read as: As long as the condition is true, execute the first block of code, and if the condition is not true, execute the second block of code.
Now we will look at a practical use of the while statement:
current = 1
end = 10
The condition of this while statement is that the current number is less than or equal to the end number:
while current <= end:
print(current)
current += 1
else:
print('You have reached the end')
Note that the statement You have reached the end is printed out only once. This demonstrates how to implement the else clause with a while statement.
The final code is as follows:
# Set the starting value
current = 1
# Set the end value
end = 10
# While the current number is less than or equal to the end number
while current <= end:
# Print the current number
print(current)
# Increment the current number by one
current += 1
else:
"""
Immediately the current number is not less than or equal to the end
number, print this statement.
Note that the statement is only printed out once
"""
print('You have reached the end')
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
1
2
3
4
5
6
7
8
9
10
You have reached the end
As expected, Python loops through all numbers from 1 to 10 and prints them out to standard output. At the end of the loop, the program prints the line You have reached the end as expected. This marks the end of program execution, and the program exits.
To show the power of while loops, let's look at an example that uses a while loop to keep an interactive Python program running until a condition is met. To do this, we will rewrite the program we wrote earlier and add a while statement:
release_year = '1991'
correct = False
while not correct:
answer = input('When was Python first released?')
Note the use of input(). This tells the terminal to wait for user keyboard input.
if answer == release_year:
print('Congratulations! That is correct.')
correct = True
else:
print('No, that's not it. Try again ')
print('Bye!')
The final code is as follows:
# Set release_year to 1991. This is the correct answer to the question to be asked
# Note that this is a string as user input is automatically set to type str
release_year = '1991'
# Set the condition "correct" to False
correct = False
# While the answer provided is not correct, keep the program running
while not correct:
# Print out the question to stdout
# Note the use of input(). This tells the terminal to wait for user keyboard input
answer = input('When was Python first released?')
# Use an if statement to check that the provided answer is correct
if answer == release_year:
# If the answer is correct, print success message to stdout
print('Congratulations! That is correct.')
# After printing message, set correct to True
# This will cause the while loop to stop executing
correct = True
else:
# If the answer is incorrect, encourage user to try again
print('No, that's not it. Try again ')
# Finally, print the exit message
# Note that this is only printed just before the program exits
print('Bye!')
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
When was Python first released? 1841
No, that's not it. Try again
When was Python first released? 2001
No, that's not it. Try again
When was Python first released? today
No, that's not it. Try again
When was Python first released? 1991
Congratulations! That is correct.
Bye!
The while loop is used in the following cases:
The aim of this activity is to create a password authentication feature using a while loop.
You have been asked to add a simple password authentication feature for a prototype that your team is setting up. One of your team members has advised the use of a while loop.
The steps are as follows:
The output should be as follows:
>python while_python.py
please enter your password: random
Welcome back user!
>python while_python.py
please enter your password: none
invalid password, try again...
please enter your password:
Solution for this activity can be found at page 283.
The main difference between an if and a while statement is that an if statement gives you the opportunity to branch the execution of code once based on a condition. The code in the if block is only executed once. For instance, if a value is greater than another, an if statement will branch out and execute a computation, and then proceed with the program's flow or exit.
A while statement, however, gives you the opportunity to run a block of code multiple times as long as a condition evaluates to true. This means that a while statement will, for example, execute a computation as long as value A is greater than value B and only proceed with the program flow when A is no longer greater than B.
In this sense, a while statement can be considered a loop. We'll look at looping structures next.
In Python, looks (just as in any other language) are a way to execute a specific block of code several times. In particular, loops are used to iterate or loop over what we call iterables.
For the purposes of this chapter, we can define an iterable as follows:
A few examples of common iterables include the following:
You can think of an iterable as a collection of homogeneous things that have been grouped together to form a large collective. The individuals in the group have the same properties, and when they are combined, they form something new.
Consider the example of cars in a car yard. We can consider the car yard as the collection or iterable and the individual cars as the constituent members of the car yard. If you were shopping for a car, you would probably have a couple of qualities that you are looking for. You walk into the car yard and start going from car to car looking for one that satisfies your conditions or comes as close as possible to satisfying your conditions. The act of going from car to car and repeating the aforementioned inspection operation is basically what looping is.
Loops allow us to deconstruct iterables and perform operations on their constituent members or even convert them into new data structures. The possibilities are endless once you start using loops.
The for loop in Python is also referred to as the for…in loop. This is due to its unique syntax that differs a bit from for loops in other languages.
A for loop is used when you have a block of code that you would like to execute repeatedly a given number of times. For example, multiplying an iterable value, or dividing the value by another if the iterable value is still present in the loop.
The loop contrasts and differs from a while statement in that in a for loop, the repeated code block is ran a predetermined number of times, while in a while statement, the code is ran an arbitrary number of times as long as a condition is satisfied.
The basic syntax of a for loop is shown here:
# Iterable here can be anything that can be looped over e.g. a list
# Member here is a single constituent of the iterable e.g. an entry in a list
for member in iterable:
# Execute this code for each constituent member of the iterable
pass
As shown in the preceding code, the for loop allows you to go through each constituent member of an iterable and run a block of code for each member. This code could be anything from a simple summation of the values to more complex manipulations and analysis. Again, the possibilities are endless, and having the ability to easily access iterables like this will prove invaluable as you start building more complex programs in Python.
A practical use of the for loop is shown here:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Create a new variable called num in the for loop. We will use this variable to represent and access the individual numbers in the list as we loop through it:
for num in numbers:
We assign the square of num to the variable square:
square = num * num
print(num ,' squared is ', square)
This loop is repeated for all ten numbers in the list.
The final code is as follows:
# Create a list with numbers 1 through 10
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Loop through the list of numbers
for num in numbers:
# Calculate the square of the number
square = num * num
# Print out a string showing the number and its calculated square
print(num ,' squared is ', square)
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
1 squared is 1
2 squared is 4
3 squared is 9
4 squared is 16
5 squared is 25
6 squared is 36
7 squared is 49
8 squared is 64
9 squared is 81
10 squared is 100
As expected, the loop iterates over the list numbers, calculates the square of each number, and prints out the result in a readable format.
As with a while statement, an else statement can also be optionally used with a for loop. In this case, the code inside the else block will be executed exactly once when the loop exits cleanly. Exiting cleanly means that the loop went through all the members of the iterable without breaking.
Here is that same code snippet from earlier with an else clause added:
# Create a list with number 1 through 10
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Loop through the list of numbers
for num in numbers:
# Calculate the square of the number
square = num * num
# Print out a string showing the number and its calculated square
print(num ,' squared is ', square)
else:
print('The last number was ', num)
The else clause is added to the very bottom of the loop.
The output from this code will be as follows:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
1 squared is 1
2 squared is 4
3 squared is 9
4 squared is 16
5 squared is 25
6 squared is 36
7 squared is 49
8 squared is 64
9 squared is 81
10 squared is 100
The last number was 10
As we can see, the else clause is executed only once and only after the rest of the code has been ran successfully. It is also important to note that although it may not seem like it, the else clause has access to all the variables created within the for loop. This can prove very valuable for debugging and handling error conditions in our code.
Python's range function is a built-in function that generates a list of numbers. This list is mostly used to iterate over using a for loop.
This function is used when you want to perform an action a predetermined number of times, where you may or may not care about the index, for instance, finding or calculating all even numbers between 0 and 100, where Python will list or print out all even numbers in that range, excluding 100, even though it is an even number. You can also use it to iterate over a list (or another iterable) while keeping track of the index.
The basic syntax of the range function is as follows:
range([start], stop, [step])
Here is a breakdown of what each parameter does:
As a general rule, when a parameter is enclosed in square brackets [] in the function definition, it means that that particular parameter is optional when you are calling the function.
This means that the only required parameter when calling the range function is the stop parameter, and the default call to the function can have just that one parameter.
Now, let's look at some calls to the range function and their corresponding output. First off, perform a call with just the stop parameter included:
range(10)
The range(10) class basically tells the function to generate numbers from 0 to 10, but not including 10. To view the numbers, we would have to cast the range object into a list object. The output of this call is shown here:
Python 3.7.0 (default, Jun 29 2018, 20:13:13)
[Clang 9.1.0 (clang-902.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> range(10)
range(0, 10)
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Please note that the range function starts at zero if a start point is not defined as with this form of the function call.
What if we wanted to create a list from 1 to 10? To achieve this, you would have to include the start parameter of the range function. You would also have to change the stop parameter, too. Remember that the stop parameter is not included in the final generated list.
The pseudo-code for what you want to achieve is: Generate a list of all numbers from 1 to 10.
Here is how we do it:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
>>> list(range(1, 11))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
How is the step parameter used? The step parameter defines the difference between each number in the generated list. If you set step to 5, the difference between each number on the list will be a constant of 5. This can be useful when you want to generate a very particular set of numbers between any given two points.
Let's write a piece of code that generates a list of all even numbers between 2 and 20. Here, we can see the application of the step parameter. We will use it to make sure that the difference between each number is 2, thus ensuring that the final list will only contain even numbers.
Here is how we can do it:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
> list(range(2, 21, 2))
> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
Conversely, you can generate a list of all odd numbers between 1 and 20 by tweaking the code a bit and changing that first parameter 2 to 1 so that the function starts at 1 instead of 2:
> list(range(1, 21, 2))
Now that we are familiar with how range() works, we can look at some practical applications of range in a real program. Consider the following code:
for num in range(1, 11):
print(num ,' squared is ', num * num)
This is a rewrite of the code that we used earlier with the for loop. The for loop code is shown here for comparison:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for num in numbers:
square = num * num
print(num ,' squared is ', square)
It is evident that we are able to achieve the same result using far less code and without having to initialize variables that may not be used outside of this loop. This helps keep our code nice and clean.
Using a for loop and a range function, you have been asked to find the even numbers between 2 and 100 and then find their sum.
The steps are as follows:
The output should be as follows:
>>> print(total)
2550
Solution for this activity can be found at page 284.
Nesting can be defined as the practice of placing loops inside other loops. Although it is frowned upon in some applications, sometimes, it is necessary to nest loops to achieve the desired effect.
One of the use cases for nesting loops is when you need to access data inside a complex data structure. It could also be as a result of a comparison of two data structures. For instance, a computation that requires values in two lists would have you loop through both lists and execute the result. It is sometimes necessary to use one or more loops inside another loop to get to that level of granularity.
In this exercise, we will utilize nested loops:
groups = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
From the structure of the list, it is clear that just looping over it will not get us to the individual integers. To get to the individual integers, we have to loop over the groups and then loop over each group.
for group in groups:
for num in group:
square = num * num
print(num ,' squared is ', square)
The final code is as follows:
# Create a list with three groups of numbers 1 through 9
groups = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# Loop through the list of number groups
for group in groups:
# Loop through numbers in group
for num in group:
# Calculate the square of the number
square = num * num
# Print out a string showing the number and it's calculated square
print(num ,' squared is ', square)
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
1 squared is 1
2 squared is 4
3 squared is 9
4 squared is 16
5 squared is 25
6 squared is 36
7 squared is 49
8 squared is 64
9 squared is 81
As you can see, we are able to loop over the individual groups of integers and perform calculations on the individual integers by nesting the for loops. This is the power of nesting: it can allow us to unpack complex structures.
There is no limit to how far you can nest loops, though you should keep code readability in mind when writing nested loops. You don't want to nest so much that you cannot easily deduce what the code does or the expected results of running the code at a glance. Remember, you are writing your code not just for the computer but for future developers who might need to work on it. Oftentimes, this future developer is you in a couple of months. You don't want to look at some code that you wrote six months from now and not be able to comprehend it. Do yourself a favor: keep it simple.
Write a simple nested loop example that sums the even and odd numbers between 1 and 11 and prints out the computation.
The steps are as follows:
The output will be as follows:
2 + 1 = 3
2 + 3 = 5
2 + 5 = 7
2 + 7 = 9
2 + 9 = 11
4 + 1 = 5
4 + 3 = 7
4 + 5 = 9
4 + 7 = 11
4 + 9 = 13
6 + 1 = 7
6 + 3 = 9
6 + 5 = 11
6 + 7 = 13
6 + 9 = 15
8 + 1 = 9
8 + 3 = 11
8 + 5 = 13
8 + 7 = 15
8 + 9 = 17
10 + 1 = 11
10 + 3 = 13
10 + 5 = 15
10 + 7 = 17
10 + 9 = 19
Solution for this activity can be found at page 284.
When running loops, sometimes, we might want to interrupt or intervene in the execution of the loops before it runs its full course due to an external factor. For instance, when writing a function looping though a list of numbers, you may want to break when a defined condition external to the program flow is met. We will demonstrate this further.
Python provides us with three statements that can be used to achieve this:
The break statement allows you to exit a loop based on an external trigger. This means that you can exit the loop based on a condition external to the loop. This statement is usually used in conjunction with a conditional if statement.
The following is an example program that shows the break statement in action:
# Loop over all numbers from 1 to 10
for number in range(1,11):
# If the number is 4, exit the loop
if number == 4:
break
# Calculate the product of number and 2
product = number * 2
# Print out the product in a friendly way
print(number, '* 2 = ', product)
print('Loop completed')
The output for this code is as follows:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
1 * 2 = 2
2 * 2 = 4
3 * 2 = 6
Loop completed
As shown by the output, the loop exits when number is equal to 4 because of the conditional if number == 4 statement.
The continue statement allows you to skip over the part of a loop where an external condition is triggered, but then goes on to complete the rest of the loop. This means that the current run of the loop will be interrupted, but the program will return to the top of the loop and continue execution from there.
As with the break statement, the continue statement is usually used in conjunction with a conditional if statement.
Here is the same code from earlier with the break statement replaced with a continue statement:
# Loop over all numbers from 1 to 10
for number in range(1,11):
# If the number is 4, continue the loop from the top
if number == 4:
continue
# Calculate the product of number and 2
product = number * 2
# Print out the product in a friendly way
print(number, '* 2 = ', product)
print('Loop completed')
The output then becomes the following:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
1 * 2 = 2
2 * 2 = 4
3 * 2 = 6
5 * 2 = 10
6 * 2 = 12
7 * 2 = 14
8 * 2 = 16
9 * 2 = 18
10 * 2 = 20
Loop completed
Note the difference between this and the output of the break statement. This loop, instead of exiting when it reached 4, simply skips over the rest of the loop when number is 4 and resumes execution at the top of the loop. The product of 4 is therefore never printed to the screen, but the rest of the output is printed normally.
The pass statement allows you to handle an external trigger condition without affecting the execution of the loop. This is to say that the loop will continue to execute as normal unless it hits a break or continue statement somewhere later in the code.
As with the other statements, the pass statement is usually used in conjunction with a conditional if statement.
Here is the code from the break statement example, with break replaced with pass:
# Loop over all numbers from 1 to 10
for number in range(1,11):
# If the number is 4, proceed as normal
if number == 4:
pass
# Calculate the product of number and 2
product = number * 2
# Print out the product in a friendly way
print(number, '* 2 = ', product)
print('Loop completed')
The output of this code will be as follows:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
1 * 2 = 2
2 * 2 = 4
3 * 2 = 6
4 * 2 = 8
5 * 2 = 10
6 * 2 = 12
7 * 2 = 14
8 * 2 = 16
9 * 2 = 18
10 * 2 = 20
Loop completed
As evident, the code encounters the condition but does nothing based on it. The pass statement simply tells the program to proceed as normal. The pass statement is also mostly used as a placeholder.
You have been asked to write a loop that outputs values in a database column ranging between 0 and 200. Zero, any number that is not divisible by 3, and any value that is not an integer, should be ignored. One of your team members has advised the use of break, continue, and pass statements.
The steps are as follows:
The output will be as follows:
3
6
9
12
15
…
…
174
177
180
183
186
189
192
195
198
Solution for this activity can be found at page 284.
In this chapter, we have learned about how programs in Python flow. We also learned how to control and branch the flow of a Python program by using the two main control statements, that is, if and while. We have also looked at some practical applications of the two control statements and have seen how they differ in implementation and syntax.
In this chapter, we have also increased our knowledge of looping structures. We have seen the structure of a for loop and looked at practical examples. We have also looked into the range function and how it comes in handy when you need to quickly iterate over a list.
Apart from that, we have also covered how and when to nest loops and how to break out of loops prematurely under different conditions and with differing results by using the break, continue, and pass statements.
Armed with this knowledge, you can now start incorporating more complex structures into your programs.
In the next chapter, we will look at functions and how to define them, the various types of functions, and how they can help us compartmentalize our code.