Week 3: Booleans, Conditionals, and Strings

Class Recordings

To access recordings, sign in with your @swarthmore.edu account.

Monday

Section 1 (Joshua)

Section 2 (Kevin)

Wednesday

Section 1 (Joshua)

Section 2 (Kevin)

Friday

Section 1 (Joshua)

Section 2 (Kevin)

Announcements

  • Quiz 1 Study guide available on course home page.

  • Quiz 1 Friday next week (Sep 24) at start of class.

  • Wednesday Ninja session good time to review!

Monday

Accumulator Pattern

A very common use of loops is to aggregate, or combine, the result of a repetitive set of steps. For example, we may want to sum the numbers from 1 to \$n\$. To create an accumulator pattern, we should first answer these questions to help us code the solution:

  • What are we accumulating? (should create a variable to store this)

  • Where does the accumulator start? (initialize variable; not always 0)

  • How many iterations/times do we loop? (use to set the range)

  • What do we need to calculate inside the loop? How do we update the accumulator (updating the variable must be a part of the loop)

  • What do we do with result of accumulation?

Together, we will show in avg.py how to use an accumulator pattern to average a series of numbers entered by a user.

Exercise: factorial

Work with a neighbor and sketch out your solution to calculating the factorial of a number. Do not start to code until you have answered all of the questions above for designing an accumulation pattern. Your program should ask the user for a number (integer) and calculate the factorial. The factorial of a number is \$n! = n \cdot (n-1) \cdot (n-2) \cdot \ldots \cdot 2 \cdot 1\$ e.g., \$5! = 5 \cdot 4 \cdot 3 \cdot 2 \cdot 1 = 120\$. Begin by answering the accumulator questions above and then start to write your program in factorial.py.

More String Operations

You’ve seen several instances of strings already this semester, and you’ve likely used string concatenation to build up a string. There are many other useful string operations. Here are some highlights:

  1. length. To get the length of a string, use the len command e.g. len("cs21") = 4

  2. indexing. Access a single character in a string using its position indexing from zero. For example, if name="Punxsutawney", then name[1] = "u".

  3. concatenation. Concatenate with the + operator. "hello" + "world" == "helloworld"

Exercise: str_practice.py

Open str_practice.py to complete four tasks and a couple of extensions if you desire. Be sure to incrementally develop — complete one task, run your program to see if that tasks works, and then move onto the next. Tasks 4 and bonus will require for loops and accumulators.

$ python3 str_practice.py 
Task 1:
Enter first name: Tina
Enter last name: Fey

Hello Tina Fey

Task 2:
There are 7 characters in your name

Task 3:
Initials: T.F.

BONUS:
Last initials: a.y.

Task 4:
T
i
n
a

T
Ti
Tin
Tina

Accumulator Pattern - Strings

Just as we saw with numbers, you can use a for loop and the accumulator pattern to build strings. To start with an empty string, initialize a variable with two quote marks that have nothing inside them (not even a space):

result = ""

You can then build up the result string by accumulation with the + operator. Let’s practice together by writing a program interests.py that asks the user for three things they like and then prints them back:

$ python3 interests.py
Tell me three things you like!

Thing 1: plants
Thing 2: video games
Thing 3: CS 21

You like: plants video games CS 21

Wednesday

Boolean Logic and Relational Operators

Our programs in the first week were entirely sequential. Each statement was processed immediately after the preceding line. In week two, we added the for loop to allow us to repeat a task a fixed number of times. This week we will introduce a new type, the Boolean type and show how to use it with branching or decision structures to optionally run code based on various conditions. Booleans and conditionals represent another computational tool we will use throughout the semester to design algorithms for problems.

The Boolean or bool type can only hold two possible values: True or False. Note in Python, both of these values begin with an upper case letter and the values do not have quotes around them. The value "True" (with quotes) is a string, not a Boolean.

One way to generate a Boolean value is to use one of the relational operators listed below. For example, the operator < compares two variables or expressions left < right. If the value of left is smaller than right, the expression left < right evaluates to True, otherwise, the answer is False.

Python’s relational operators are:

Operator Meaning

<

less than

<=

less than or equal to

>

greater than

>=

greater than or equal to

==

equal to

!=

not equal to

Note that to check if two expressions are equal, you must use the ==, e.g., x == 7. Using x = 7 in Python has a different semantic meaning — it performs a variable assignment and stores the value of 7 in the container labeled x.

Exercise: practice relational operators

What are the bool values that result from the following expressions? Assume x = 10. First, try to predict the value, then you can check your answers in an interactive Python shell by typing python3 in the terminal.

x < 10
x >= 10
x != 15
x + 15 <= 20
x % 2 == 1

Note: % is the mod or remainder operator. x % y returns the remainder when x is divided by y using integer division.

Branching with if

Programmers use branching, or conditional statements, to run different code based on the state of the program. The simplest form of branching is an if statement:

if <condition>:
    <body>

Here, <condition> should be a statement that evaluates to a Boolean value. The code inside the <body> only runs if the condition is True. Here’s an example program that warns you only if the temperature is below freezing:

def main():
    temp = int(input("Enter temperature: "))
    if temp < 32:
        print("Freezing temperatures; be sure to wear a coat!")
    print("Have a great day!")

main()

Note the use of the : as we saw at the end of for loops and the main() function. Like those constructs, the <body> of an if must be indented to indicate that it should execute together as part of the if statement.

Other Branching Structures

In addition to the basic if statement, Python supports two additional variants: if/else and if/elif/else. The general form of the if/else is:

if <condition>:
    <body>
else:
    <else-body>

Again, if the <condition> evaluates to True, Python executes the code in <body>. However, if the condition is False, Python executes the code in <else-body> instead. Regardless of the value of <condition>, exactly one of <body> or <else-body> will run, but not both. It is possible to have an if with no else, but any else must be paired with a matching if statement.

We could modify the program above to print a different message if temp is above freezing. Regardless of the temp value, the program will always print Have a great day! since this message is printed outside the body of either the if or the else as noted by the indentation.

def main():
    if temp < 32:
        print("Freezing temperatures; be sure to wear a coat!")
    else:
        print("Spring is on its way!")
    print("Have a great day!")

main()

The final, most complex branching variant is the if/elif/else:

if <cond-1>:
    <body-1>
elif <cond-2>:
    <body-2>
elif <cond-3>:
    <body-3>
...
else:
    <else-body>

All of these statements work together as one large decision block. Python will first evaluate <cond-1> and if it’s True, it will execute <body-1> then skip over the remaining bodies in the block. If <cond-1> is False, Python will next evaluate <cond-2>. If that is True, it will execute <body-2> and then skip over all the remaining bodies in the block. We can continue to add more elif conditions and bodies, but each condition will only be evaluated if all the other previous conditions were False. Finally if all the condition checks evaluate to False, Python executes the <else-body>, if there is one. You can have an if/elif/elif/…​ with no final else.

In summary, a decision block has a mandatory if <condition>: at the beginning, and optional else: at the end, and zero or more elif <condition-k>: statements in the middle.

Exercise: practice if statements

Practice if/else statements by writing a block of code (in cs21/inclass/w03/voting.py) that determines if a person’s age makes them eligible to vote (18 or older on election day).

Some potential output might look like:

$ python voting.py
Enter your age on election day: 20
You are eligible to vote

$ python voting.py
Enter your age on election day: 18
You are eligible to vote

$ python voting.py
Enter your age on election day: 2
You can't vote this year
You will need to wait 16 years

Friday

Code tracing is when you run through code in your head and try to determine the result. I have provided three blocks (the last purposefully being harder than the other two). What will each of these blocks do? Do they give different results, or are some of them equivalent in terms of what they print?

#Block 1
if temp >= 60:
    print("No coat is needed")
if temp >= 40:
    print("Spring jacket")
#Block 2
if temp >= 60:
    print("No coat is needed")
elif temp >= 40:
    print("Spring jacket")
#Block3
if temp >= 40:
    if temp >= 60:
        print("No coat is needed")
    else:
        print("Spring jacket")

Logical Operators

In many programs, it’s convenient to ask compound questions or require multiple conditions be True before executing some code. In these cases, we can join to questions together using a logical operator:

Operator Meaning

and

both boolean expressions must be true

or

at least one of the two boolean expressions must be true

not

negates the boolean value

Below is a truth table, where x and y represent Boolean values or expressions. For example, x could be age >= 18 and y could be status == "Yes". Each row should be read as follows: for the given Boolean values of x and y, what is the result of x and y, x or y, and not x:

x y x and y x or y not x

True

True

True

True

False

True

False

False

True

False

False

True

False

True

True

False

False

False

False

True

Python’s precedence rules evaluate operators in this order:

  1. Evaluate anything inside of ()

  2. Evaluate all relational operators

  3. Apply any not operators

  4. Evaluate and operators

  5. Evaluate or operators.

  6. If tied, evaluate left to right.

For example, suppose b = 5 and c = 10 and a program encounters this line:

not True or b < 10 and c != 5

Python first evaluates b < 10 (True) and c != 5 (True). Thus, we can simplify the line to:

not True or True and True

Next, Python evaluates not True (False), leaving:

False or True and True

Next, it evaluates the True and True clause, which is also True. All that’s left is:

False or True

Finally, Python evaluates the or, whose result is True.

Exercise: Logic Tests

For this exercise, use the program logicTests.py to test your understanding of logical operators. You don’t need to write any code for this exercise, just run the program and follow the prompts.

$ python3 logicTests.py

Exercise: Water Phase

Write a program in phase.py that, given a temperature in °C, prints the phase of water at that temp assuming standard pressure.

$ python3 phase.py
Enter a temp in °C: 150
At 150C, water is a gas

$ python3 phase.py
Enter a temp in °C: 20
At 20C, water is a liquid

$ python3 phase.py
Enter a temp in °C: -10
At -10C, water is a solid

Comparing Strings

We can compare string values just as we can compare integer and float values. That is, we can use any relational operator on a pair of a strings.

"Aardvark" < "Baboon"

Strings in python3 are compared lexicographically, i.e., based on their sorted dictionary order. So, the above expression is True because Aardvark appears earlier in the dictionary than Baboon.

Python actually compares the two strings character-by-character until it finds a difference. So, it will first compare A to B. It finds that they are different, and so it returns True. If the expression is:

"Apple" < "Applied"

Python first compares the A s, then each p, then the l s , and finally stops at the next position since e and i are different. Since e comes before i in the alphabet, the expression returns True.

What if we had:

"apple" < "APPLE"

What does Python do here? Internally, everything in the computer is represented numerically in binary (0s and 1s). So, even text is really represented as a series of numbers (positive integers, specifically). The encoding, or conversion, is known as Unicode. We can find the conversion using the ord() function:

$ python3
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> ord('A')
65
>>> ord('B')
66
>>> ord('Z')
90
>>> ord('!')
33

So to answer our question above, we need to compare the Unicode value of a to A. A is a small Unicode value, so the expression is False.

We can also convert in the other direction - from a number to a character using the chr() function:

>>> chr(58)
':'
>>> chr(100)
'd'
>>> chr(75)
'K'