Unit 2 - Programming Fundamentals: Conditionals and Loops
2.0. Boolean Expressions and Conditionals
2.0.0. Overview
In this session we'll take our first look at boolean expressions, statements which evaluate to True or False and form the foundation of conditional statements (if-elif-else ) and conditional loops ( while ).
2.1. Branching Structures
A branching structure is an element in a program that allows a decision to be made, depending on some condition. In Python, the branching structure is the if statement.
2.1.0. The if statement
if statements
Python's branching structure is the if statement. In its most basic form, it looks like this:
The Boolean condition has a value that is True or False. If the condition is True, the 3 statements in the indented suite will be executed, and then the statement following that suite will be executed. If the condition is False, the 3 statements are skipped, and only the statement following the suite is executed. (Note that the suite has been indented 4 spaces, the standard in Python.
Let's see what a Boolean expressions looks like.
2.1.1 Boolean expressions
Boolean expressions
Boolean expressions evaluate as "True" or "False".
The most common way to create a Boolean expression is to compare two values using a comparative operator like <, >, ==, or != (not equals).
Here, the boolean expression age >= 18 will evaluate as True if the value of age is greater than or equal to 18, and because it's true, the two print statements that are indented below will be executed. If age is less than 18, however, that expression will evaluate to False, and those two lines will be skipped. Either way, the line following the indented suite (block) of code will be performed.
One can also create a boolean expression simply by assigning a variable the value True or False.
Examples:
- user_age_greater_than_18 = False
- its_my_birthday = True
The comparative operators include:
== | means "is equal to" |
!= | means "is NOT equal to" |
< | means "is less than" |
> | means "is greater than |
<= | means "is less than or equal to" |
>= | means "is greater than or equal to" |
2.1.2. Boolean expressions in branching statements
Let's take a look at how boolean expressions might be used in actual statements.
Predict the result
Examine each of these examples and predict what you think the output will be.
2.1.3. if-else statements
There are additional forms of the if statement that often come in handy:
if-else statements
If you want to manage a 2-way condition (either do this, or that), use the if-else statement:
Note that the if and else suites (or blocks) are indented 4 spaces, which helps us visualize that they are the two different options in this part of the program.
Thus, we can correctly analyze whether or not someone is age-eligible to be president with the following code:
Only one of the two blocks of code will be executed, depending on the value of the variable age.
Let's try writing a new program.
Try this
A restaurant serves breakfast and lunch until 4pm (1600 hours on a 24-hour time clock), at which time it starts serving dinner. Write a program that has the user enter a 24-hour time, and then indicates whether the restaurant is serving lunch or dinner at that time.
2.1.4. Multiple if statements
Some problems require that there be more than a single option considered. For these cases, you basically have two possible ways two write the code:
- Organize your logical solution so that a series of if-else statements can be nested, allowing the program's logic to drill down to find the appropriate action, or
- if the actions can all be considered simultaneously, use an if-elif-else statement.
Usually one strategy will recommend itself over the other. The next two examples show how each of the strategies can be used to solve the problem of calculating the roots of a quadratic equation.
nested if-else Quadratic Eqn solver
Example of using a nested if-else statement to solve a quadratic equation:
if-elif-else Quadratic Eqn solver
Example of using an if-elif-else statement to solve a quadratic equation:
Let's try a simple exercise to put some of these pieces together:
Try this
A restaurant is open for breakfast until 1100 hours, for lunch until 1600 hours, and for dinner until 2300 hours. Write a program that has the user enter the time (in 24-hour form), and then prints out meal the restaurant is serving at that time. Include an additional print statement for each meal that recommends a beverage suitable for that meal. Regardless of the hour, print out the message "Thank you for choosing our restaurant."
2.1.5. Additional Boolean expressions
There are three more Boolean operators that one can use to create more complex Boolean expressions.
Boolean operators and, or, and not
<Boolean expression A> and <Boolean expression B>
is only true of both Boolean expressions A and B are True.
<Boolean expression A> or <Boolean expression B>
is true if either one of the Boolean expressions A and B are True.
not <Boolean expression A>
is only true of Boolean expression A is False.
Example:
if age >= 13 and age <= 19:
print("You're a teenager.")
else:
print("You're not a teenager."
Try this
Triangles can be identified as equilateral, isosceles, or scalene depending on how many sides have the same length. Write a program that asks the user to enter the lengths of three sides for a triangle, and then tells them what kind of triangle it is.
2.1.6. Boolean variables
As you become more comfortable with Boolean expressions that compare values, you will want to start creating and using Boolean variables that have a value of True or False. These have the advantage of making your program easier to read.
What does that look like? Above, we were doing an analysis of somebody's age and printing out whether or not they were a teenager. We could use a boolean variable to perform that same analysis:
And then later on in the program, perhaps:
For a single boolean analysis, this might not seem like it's any advantage, but for a complex analysis, it is often helpful to reduce your comparisons to Boolean variables.
2.2. while Loops
When we need to repeat a series of instructions in program, we use a loop structure. The type of structure you choose to use will usually depend on what kind of repetition you want to provide for.
Loops
A loop is a series of instructions that may be repeated over and over according to certain conditions.
In Python, there are two main types of loop structures: while loops and for loops.
2.2.0. Overview
When we don't know in advance how many times a program should repeat something, we usually use an indefinite loop, and in Python, the most important looping structure is the while loop.
2.2.1. Indefinite Loops
The while loop is typically used when you have a loop that needs to repeat some number of times, based on a condition. "While we haven't finished adding up this list of numbers, keep adding," for example.
The while loop
The while loop is a conditional loop: it keeps repeating as long as a condition is True.
For our first example of a while-loop, let's begin with an if statement that prints out a "Hello" message when person enters a name. If they don't enter anything, however, we won't print anything. Either way, we'll tell them the program is done when it's over.
This program works fine, but we can also modify it so that it says hello to a series of people, with just a couple of changes.
Take a look at this version of the program. It will say "hello" to each person until the empty string ("") is entered, where "" is the sentinel value for the loop.
Here, the sentinel value that will end the loop is the empty string "". As long as name doesn't have the value "", the loop will continue to run, saying "Hello" using every name that is entered. Once no value ("") is entered, the boolean expression becomes False and the body of the loop is not executed. Instead, execution proceeds to the line below the body of the loop.
Sample output:
A sentinel value can be used in lots of different applications. One common example is playing a game. The program will play a game, then ask the user if they want to play again. As long as the user doesn't enter the sentinel value of "No" (or "Quit", etc.), the game loop keeps repeating.
2.2.2 Using while loops to validate input
Your program will be more robust, and less fragile, if it attempts to validate input, making sure that the data coming in to the program is appropriate.
Not validating input makes your program easier to break, and in security applications, can be downright dangerous to your program, your user's data, and your computer.
Here are two quick examples of how you can use a while loop to validate a user's input after he/she has entered it.
Here's another way to do the same thing. This next version of the program uses a loop that would repeat infinitely, except for the fact that—once we get the positive number that we're looking for—we use the break statement to break out of the loop.
2.2.3. Counting with a while loop
A loop can also be used for is repeating something a specified number of times. Here's a while loop that counts from 0 to 9, repeating the body of the loop 10 times.
The output of this loop:
There are a couple of important things to note about this loop. We've started with the variable i at 0, and when we do that, the value 10 in the statement while i < 10 indicates the number of times that the loop will repeat. That's a pattern that we'll see often. Also, the loop does run ten times as it counts from 0 to 9. Starting our counting at 0 instead of at 1, may seem strange, but this is something that computer science people do all the time, so you'll need to get used to it: the first index (or value) that we count with is almost always 0.
If you want to have your loop print out the numbers from 1 to 10 there are a number of ways you can do that. (Try to figure out what some of them are!) But as for most of the loops we use, the variable will start at index 0.
2.2.4. Interactive loops
The interactive loop allows the user to interact with the instructions in a loop. Here's an example where we'll add a series of numbers.
This loop works pretty well, but one of the problems is that it's annoying for a user to have to approve every iteration.
2.2.5. More sentinel loops
One way of solving the problem of having to have a user repeatedly indicate that he/she wants to continue is by using a sentinel value. This value, when entered with the other numbers, will indicate to the loop that it should stop running.
We saw an example of this above:
Counting things
It's a common task for a computer program to have to count things. Modify the "Hello" program above to count how many names are entered, and report the result once the sentinel value has been entered.
Here's an example of another sentinel loop: have the user enter each number as a string so that we can use a sentinel value of "". If we're going to be using the values entered as numbers, we'll need to convert them so that we can do math with them.
This is the best version yet of this program.
2.2.6. Activity: number_guessing_game.py
Write a program...
Write a program that plays a number guessing game with the user. The program should ask the user if they'd like to play a guessing game. If the user wants to, the program picks a random number between 1 and 10 inclusive, and the user has three chances to guess the number. After each guess, the program tells the user if they got it right, if the guess was too high, or if the guess was too low. After the user has guessed the number or the user has had three guesses, whichever comes first, the guessing game is over. The program should then ask the user if s/he wants to play again.
If you're working on this problem on your own, you might want to get some advice on how to go about developing your program here.
- Write an initial sentinel loop asking user if they want to play a game. If 'y', play the game (insert a pass statement in place of the body), then ask if they want to play again. Note that we're not writing the body of the game yet, we're just getting the "play again" loop set up.
- add goodbye message for after they don't want to play anymore
- develop basic game:
- Make up a random number between 1 and 10
- Get the user's guess
- Tell them whether they got it right or not
- This is just a one-number guessing game. We want to set it up so that they can have three guesses before the game is over.
- multiple-guessing code:
- Set up another while loop that counts how many times they've guessed, and we'll only give them 3 guesses. We need a new variable to keep track of the guess_number
- Give a hint as to whether we guessed too high or too low
- Need to stop asking them for guesses if they got it right--expand conditional to while (guess_number < 4 and the_guess != the_number):
2.2.7. Programming Project - coinflipper.py
For our first larger project, we're going to need a little outside help in writing the program. We're also going to introduce the format for the larger projects, which should give you the support you need to complete these assignments as required. This project is not actually much larger than the programs that we've been writing, so that makes it ideal for helping to ramp up your code-writing abilities.
2.2.7.0. coinflipper.py
Take a moment to get the coinflipper assignment. As much as you might consider it convenient to just work off an electronic copy on the computer, go ahead and print it on paper. It's almost always a good idea to be able to draw on the paper copy, highlight certain key ideas or components, maybe even sketch a quick flowchart or pseudocode of your solution to the program. These are things that are done more quickly and easily with a pen/pencil on paper, rather than on a keyboard. Save the keyboard for actual coding.
Got the printout? Good. Take a look at the assignment and get started.
We'll pick up where we left off here once you've completed the coinflipper assignment.
2.2.8. Code Review
You can quickly improve both your coding and your debugging skills by examining programs that other people have written.
Be sure you take a few moments to go over other people's programs, see what techniques they've used that you hadn't though of, or see how their programs might be improved.
You'll quickly come to realize how important good comments are in a program, as well as using "self-commenting" variables that help one to understand how a program works.
2.3. Project: Craps
2.3.0. Overview
We are just about at a point where our projects are too big to fit into a single "program," and that's going to require a slight modification to our thinking about our programs. Before we jump into that, though, let's make a program that will allow the user to play craps on the computer.
2.3.1. Craps Assignment
Print out the Craps assignment. As before, draw on your printout, highlight important details and make a sketch, a flowchart, and/or pseudocode of your program.
Creating a good flowchart of your program is especially useful in determining how you will organize your code in terms of both loop structures and branching structures. It's all too easy to jump into coding before you have a real sense of how you're going to systematically solve your problem. So stop... take a moment to draw up a flowchart.
Compare your flowchart with mine. They don't have to look exactly the same, but they shouldn't be too far off from each other.
You might consider looking at some advice on YouTube: part 1 and part 2.
You might also consult this pseudocode.
Once you think you have a good idea of what you want to do, open up a text editor and get coding!
2.3.2. Different structures for programs
Which of these structures most closely matches what you're writing for your program?
What are the advantages and disadvantages of each of these possible structures?
2.4. for Loops
2.4.0. Overview
Computers are good at calculating, and computers are good at repeating things very quickly.
The control structure that allows us to tell a computer how to repeat instructions is called a loop.
2.4.1. The for Loop
In programming, sometimes you'll know exactly how many times a loop is supposed to repeat before it's finished. For a loop that counts from 0 to 9 (a total of 10 times), we could use a while loop:
This process of counting a specified number of times is so common in computer science that Python provides for a specialized definite loop called the for loop.
The indexed for loop
The loop is a definite loop structure that repeats a body of instruction a specified number of times.
Some common examples of the for-loop syntax include:
If someone were to ask you to write a program that called helloworldmultiples.py to print "Hello, world!" five times, you might write something like this:
Being able to write a program to do something a fixed number of times is nice, but we don't want to have to rewrite the program every time the number changes. What if we wanted to have "Hello, world!" print a different number of times, depending on what the user wants?
Inputting values
Enter this code and run the program.
Example with an error
Enter the following program and see what happens when you run it:
Did it work? If not, you'll have to debug the program to get it running.
Note that the body of the loop—the part that's going to be repeated over and over—gets indented 4 spaces as a code block. Any statement that is indented, and thus in the code block, will be repeated as part of the loop. When you don't want the next statement to be part of the body of the loop, you stop indenting. That next statement, then, is where execution of the program will begin after the loop has finished running.
Corrected example
Make one modification to your program—unindent the print "Goodbye." statement by 4 spaces—and see what happens when you run it:
What do you think the variable i was doing while the program ran through this loop?
Counter variables
Modify the program so the body of the loop has two print statements: one that prints the value of i, and one that prints out "Hello, world!"
In this program there were two code "blocks": the main function indented 4 spaces, and the "body" of the for loop which is indented 8 spaces.
This program uses a variable i to store a value that changes as the program runs. First the value 0 is stored in i during the first iteration of the loop, and the code block beneath is executed with the value 0 used anytime i is mentioned.
At the end of the code block, execution returns to the top of the code block, but now with i having a value of 1. The variable i gets successive values stored in it as the loop repeats over and over, ten times, with i running from 0 to 9. After that, the loop stops, and execution continues on to the next line below the loop.
2.4.2. Collection-based for loops
A loop can also go through a series of values specified in a tuple or list (we'll talk about these soon):
Given this, let's re-examine our definition of a for-loop.
The for loop
The for loop has the following syntax:
<sequence> may be:
- an actual sequence of values, like [1,3,5,7,9]
- something like range(10), which begins at 0 and goes up to one less than 10
- something like range(1,10), which starts at 1 and goes until the number before 10
- something like range(1,10,2), which begins at 1 and goes up by 2 until just before 10
- some other sequence of values, like ['alice', 'bob', 'charlie', 'dave'], which goes through the loop for times, with each name assigned in turn to the variable
Use the explanation of the for loop syntax in the green box above to analyze each of the following loops.
Predict the output
Predict what you think will be outputted by each of these loops. Then enter them into a program or the Python interpreter, and see what happens.
Well, let's try writing a small program to practice using a simple function.
99 bottles of beer on the wall
Write a short program called 99_bottles.py to print all the lyrics to the song "99 bottles of beer on the wall." The program should use a single function "print_lyrics," that takes a single integer parameter to print out a verse of the song. The main program should then call that function from inside a loop.
2.4.3. Nested loops
There are some problems or applications that require using a loop inside another loop.
Consider a bank, for example, and this pseudocode that identifies how much money its clients have deposited there:
Or, an analysis of the pixels in a photo (which we'll do very soon):
2.4.4. Random Walkers
A random walker moves randomly through some space: along a one-dimensional number line, around a 2-dimensional grid, or through 3-dimensional space.
We can easily track a random walker by placing it at the center, choosing a random direction, and then changing the walker's x
and/or y
coordinates. And keep on doing that until the walker returns to its starting position, if it ever does.
Although we can track the walker's coordinates by simply printing them out in a program, it's probably more fun to be able to actually watch the walker moving around on the screen.
Let's use nested loops to print out a walker, represented by an @
, on the screen.
for row in range(20): for col in range(80): if col == x and row == y: print("@",end='') elif col = 40 and row = 10: print("+",end='') else: print(".",end='') print() # go down to the next row print("x=",x,"y=",y)
2.4.5. Removing Magic Numbers
The numbers 20
and 80
in the code above are "magic numbers": they represent the width and height of the grid, but it may not be immediately obvious to a human reading our program. Likewise, the 40
and the 10
represent the middle of the screen, but that's not immediately evident unless you already understand the program. And what happens if we change the width of the screen to 90? Are you going to go looking through your code to find every place where you might have referred to the width of the screen, and change all those to new magic numbers?
There's a better way. Let's represent those values as constants, variables that are customarily written in all capital letters (meaning they shouldn't change as the program is running).
for row in range(HEIGHT): for col in range(WIDTH): if col == x and row == y: print("@",end='') elif col == WIDTH / 2 and row == HEIGHT / 2: print("+",end='') else: print(".",end='') print() # go down to the next row print("x=",x,"y=",y)
Much better!
2.5. Control Structures
2.5.0 Overview
In this session we'll take take a large-scale overview of the control structures that can be used to manage the execution of instructions in your programs. We'll also begin your first project in this course, coinflipper.
2.5.1. Control Structures - Putting the pieces together
At this point, we've just gotten to where we're starting to have some familiarity with the two main strategies that a programmer uses in describing a programs operation.
- Loop structures allow us to make a program repeat certain sections of code
- Branching structures allow us to make the program execute different sections of code, depending on whether some condition is True or False
At this point, you might be surprised to learn that you now know just about everything about controlling execution in a program. Programs are made of sections of code that are controlled by loops and branches, combined in various ways that are determined by you, the programmer.
When looking at a computer program, or when thinking about writing a computer program, it may help you to think of the program as consisting of little chunks of code, all connected by looping and branching statements, kind of like these Lego blocks.
By carefully arranging the blocks of code, and creating the statement that need to be written by you for each block of code, we develop programs of increasing power and complexity.
A nested loop:
And when things get really crazy:
It's nice to know that we've got some of the basic building blocks down, though.
There's still a lot to learn, of course. We need to examine how different types of data are stored ("data structures"), how to logically organize our programs ("functions" and "classes"), and additional ways of getting input, and delivering output.
Now try this one. It's going to use branching and looping in the same program.
Try this: multiple_greetings.py
Write a program that asks the user to enter an integer. If the number is greater than 0, the program prints out a "Hello" message that many times. If the number is not greater than 0, the program should print out a brief error message telling them what they did wrong and then end.
Now, modify the program slightly so that it doesn't end if they enter a negative number. Instead, it should keep asking them for input until they enter a positive number.