CSc 250: Lecture Notes: if-statements and while-loops in python

Review

Now that we know how to write python scripts with functions inside of them, we can learn how to do more interesting and intricate things with our programs. In this section, we will be talking about python conditionals and loops.

Conditionals

We have already done of lot of work with bash conditionals. By now, you should be pretty familiar and comfortable with using them. Conditionals in python look rather similar, but there are a few key differences that you’ll notice as we go through this lesson.

Let’s start by taking a look at the basic syntax of a conditional-statement (also called an if-statement) in python, and comparing it to the syntax used in bash. In bash, a basic conditional statement looks like this:

if [ SOMETHING ] ;
then
    CMD 1
    CMD 2
    ...
    CMD N
fi

This is saying “If SOMETHING is true, then do CMD1, CMD2CMD N.” In python, the syntax is similar:

if SOMETHING:
    STMT 1
    STMT 2
    ...
    STMT N

In English, this reads “If SOMETHING is true, then do STMT 1, STMT 2, … STMT N.” This looks very similar, but notice a few key differences:

In bash, the body of the conditional begins at the then and ends at the fi. Between those two identifiers, the code-writer can write commands in any way they want, and indenting the code is optional.

In python, the body of a conditional is specified differently. The body is made up of all sequential lines of code below the if SOMETHING: and is indented at least four spaces more it. Because of this, there is no need for an explicit fi ending to the if. Thus, indentation is strictly required when doing conditionals in python. The body of the if statement ends when a non-indented line of code is encountered following the statement.

Let’s do another comparison between the two syntaxes. Here is bash conditional with multiple if/elif/else cases:

if [ THING1 ] ;
then
    CMD 1
    CMD 2
elif [ THING2 ];
then
    CMD X
    CMD Y
else
    CMD A
    CMD B
fi

The equivalent in python is:

if THING1:
    STMT 1
    STMT 2
elif THING2:
    STMT X
    STMT Y
else:
    STMT A
    STMT B

Again, the syntax is recognizable, but there are distinctions. As with the last one there are no square brackets, no then special-token, no fi special-token, and a colon is used instead of a semi-colon.

Now let’s look at some actual examples, and take a closer look at what types of expressions can be used in the condition of the if-statement itself.

Back in lecture notes 4 we used the following as a simple example of how to write an actual, runnable bash script that uses a conditional statement. Below is a simplified version of that example:

#!/bin/bash

SERIES="StarWars"

if [ "${SERIES}" = "StarWars" ]; then
    echo "Episide 5: The Empire Strikes Back"
    echo "Episide 6: The Return of the Jedi"
elif [ "${SERIES}" = "LOTR" ]; then
    echo "The Two Towers"
    echo "The Return of the King"
elif [ "${SERIES}" = "IndianaJones" ]; then
    echo "The Temple of Doom"
    echo "The Last Crusade"
else
    echo "I do not recognize: ${SERIES}"
fi

Knowing what you know about python conditional statements, printing, and strings, what do you think a python script with equivalent behavior/functionality would look like? Try implementing this on your own, and we will discuss the solution soon…

Done?

Ok, here is the equivalent python solution:

# Notice that we make the series variable lower-case.
# This is the correct format for python!
series = "StarWars"

if series == "StarWars":
    print("Episode 5: The Empire Strikes Back")
    print("Episode 6: The Return of the Jedi")
elif series == "LOTR":
    print("The Two Towers")
    print("The Return of the King)
elif series == "IndianaJones":
    print("The Temple of Doom")
    print("The Last Crusade")
else:
    print("I do not recognize" + series)

Functionally, this behaves the exact same way as the bash version, but we have implemented it in a different language.

For if-statements, in-between the if and the : you can write any python expressions that evaluates to either True or False. In the last lecture notes, we looked at examples of expressions that evaluated to True or False. Often, these expressions compare strings for equality or compare the value of two numbers. You can even call a function directly between the if and the : if it returns a boolean value!

Let’s look at another example. In this one, we will write a function, and the condition will use the value passed as an argument when checking the condition.

def get_letter_grade(percent):
    if percent >= 90:
        return 'A'
    elif percent >= 80:
        return 'B'
    elif percent >= 70:
        return 'C'
    elif percent >= 60:
        return 'D'
    else:
        return 'F'

In this if-statement, each condition check compares the value of two numbers. When called a few times with various arguments, we can see it gives us the result we anticipate.

>>> get_letter_grade(91)
'A'
>>> get_letter_grade(78)
'C'
>>> get_letter_grade(45)
'F'

Below is an example of another function that has some conditional statements, and the conditions use the value returned by get_letter_grade. This demonstrates another way in which a programmer can construct the condition for a conditional statement.

def print_grade_summary(percent):
    letter = get_letter_grade(percent)
    if letter == 'A' or letter == 'B':
        print('Nice work! Good Grade!')
    elif letter == 'C':
        print('Cutting it close!')
    else:
        print('Put some more work in!')

In the above if-statement, string comparison is used in the condition instead of numbers. Also, notice that the first part of the if statement uses an or to combine the value of two separate comparisons that return booleans. If either letter == 'A' or letter == 'B' is true, the first case of the if-statement will be executed. Below are a few examples of calling this function:

>>> print_grade_summary(60)
Put some more work in!
>>> print_grade_summary(72)
Cutting it close!
>>> print_grade_summary(84)
Nice work! Good Grade!

Make sure you fully understand how any why these two functions behave the way they do.

While Loops

We have already discussed bash loops (for loops) in this course, so you should be familiar with the concept of looping. As with bash, python has multiple types of loops (for loops and while loops). In bash, we started by looking at for loops and focussed most of our attention on this type of loop. In python, we are going to study both while and for loops in depth. However, we are going to start with while loops. Before learning about for loops, we need to learn about lists, which is a topic yet-to-be-studied.

The general syntax of while loops is similar to the look of a conditional, and follows similar syntactical rules.

while SOME_CONDITION:
    STMT 1
    STMT 2
    ...
    STMT N

In English, this reads “While SOME_CONDITION is a true expression, execute the sequence of python statements STMT 1, STMT 2, … STMT N repeatedly.” Similar to if-statements, SOME_CONDITION can be any expressions that evaluates to a boolean (True or False). As long as SOME_CONDITION evaluates to True, the sequence of python statements will keep on executing. Once it evaluates to False, the loop with be exited and execution will continue after it.

Like if-statements, we use a colon to end the condition, and the body of the loop must be indented four spaces.

Let’s start with a super-basic example:

while True:
    print("Hi There!")

If we put this in a script and then ran it, what do you think it would do?

$ python3.6 while-true.sh
Hi There!
Hi There!
Hi There!
Hi There!
Hi There!
Hi There!
Hi There!
Hi There!
...

Running this script will actually print "Hi There!" forever (or until you quit the program, or until your computer dies). Why is this? In the loop condition, we put the expression True in the condition. Obviously, this will always evaluate to true, so the statement(s) within the body of the loop will loop through and execute forever.

Let’s try another more complex example. We will use a variable to limit the number of times that the while loop will iterate through the body of statements.

count = 1
while count <= 5:
    print ("The count is " + str(count))
    count = count + 1

If we put this in a script and run it, we get:

$ python3.6 while-count.sh
The count is 1
The count is 2
The count is 3
The count is 4
The count is 5

In this case, the body of the loop only executed 5 times. In this loop, the condition is count <= 5. Thus once the value of count is 6 or more, the loop will have to exit. count starts out having the value 0. However, the statement count = count + 1 adds 1 to the value of count each time the body of the loop is executed. Every time the body of the loop executes, count gets bigger. Eventually, it becomes large enough to make the condition expression False, and the while loop exits.

Below is another even more complex example. In this one, the while loop is in a function whose job it is to print out text-art tree. The argument specified the height that the tree should have. This argument is used in the loop to compute how the tree should be printed/displayed.

def print_tree(height):
    count = 0
    while count < height:
        width = (count * 2 + 1)
        space = (height - count);
        print(' ' * space + '^' * width)
        count = count + 1

Here are a few executions of this loop:

>>> print_tree(1)
^
>>> print_tree(3)
  ^
 ^^^
^^^^^
>>> print_tree(5)
    ^
   ^^^
  ^^^^^
 ^^^^^^^
^^^^^^^^^
>>> print_tree(12)
           ^
          ^^^
         ^^^^^
        ^^^^^^^
       ^^^^^^^^^
      ^^^^^^^^^^^
     ^^^^^^^^^^^^^
    ^^^^^^^^^^^^^^^
   ^^^^^^^^^^^^^^^^^
  ^^^^^^^^^^^^^^^^^^^
 ^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^

Let’s modify this function to use an if-statement within the while loop. We will use the if to print alternating patterns in the tree being printed.

def print_pattern_tree(height):
    count = 0
    while count < height:
        width = (count * 2 + 1)
        space = (height - count);
        if count % 2 == 0:
            print(' ' * space + '^' * width)
        else:
            print(' ' * space + '~' * width)
        count = count + 1

Here are a few runs:

>>> print_pattern_tree(5)
    ^
   ~~~
  ^^^^^
 ~~~~~~~
^^^^^^^^^
>>> print_pattern_tree(15)
              ^
             ~~~
            ^^^^^
           ~~~~~~~
          ^^^^^^^^^
         ~~~~~~~~~~~
        ^^^^^^^^^^^^^
       ~~~~~~~~~~~~~~~
      ^^^^^^^^^^^^^^^^^
     ~~~~~~~~~~~~~~~~~~~
    ^^^^^^^^^^^^^^^^^^^^^
   ~~~~~~~~~~~~~~~~~~~~~~~
  ^^^^^^^^^^^^^^^^^^^^^^^^^
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

As with bash, we can nest loops within loops, nest loops within if-statements, if-statements within loops, etc. Below is a script named ridge-trees.py that has a function with several levels of such nesting

# This functions prints a text-art tree to standard output.
# The first argument (ridges) specifies the number of ridges the tree will have.
# The second argument (ridge_height) specifies the height of each ridge on the tree.
def print_tree_with_ridges(ridges, ridge_height):    
    width = (ridges*3) + ridge_height
    i = 0                     
    while i < ridges:         
        j = 0                 
        while j < ridge_height:
            total = (i * 3 + j)
            space = (width - total) // 2
            print( ' ' * space + '^' * total + ' ' * space )
            j = j+1           
        i = i+1

print_tree_with_ridges(6, 8)
print_tree_with_ridges(5, 10) 
print_tree_with_ridges(3, 8)

Below is what running this script generates:

$ python3.6 ridge-trees.py
                          
            ^            
            ^^            
           ^^^           
           ^^^^           
          ^^^^^          
          ^^^^^^          
         ^^^^^^^         
           ^^^           
           ^^^^           
          ^^^^^          
          ^^^^^^          
         ^^^^^^^         
         ^^^^^^^^         
        ^^^^^^^^^        
        ^^^^^^^^^^        
          ^^^^^^          
         ^^^^^^^         
         ^^^^^^^^         
        ^^^^^^^^^        
        ^^^^^^^^^^        
       ^^^^^^^^^^^       
       ^^^^^^^^^^^^       
      ^^^^^^^^^^^^^      
        ^^^^^^^^^        
        ^^^^^^^^^^        
       ^^^^^^^^^^^       
       ^^^^^^^^^^^^       
      ^^^^^^^^^^^^^      
      ^^^^^^^^^^^^^^      
     ^^^^^^^^^^^^^^^     
     ^^^^^^^^^^^^^^^^     
       ^^^^^^^^^^^^       
      ^^^^^^^^^^^^^      
      ^^^^^^^^^^^^^^      
     ^^^^^^^^^^^^^^^     
     ^^^^^^^^^^^^^^^^     
    ^^^^^^^^^^^^^^^^^    
    ^^^^^^^^^^^^^^^^^^    
   ^^^^^^^^^^^^^^^^^^^   
     ^^^^^^^^^^^^^^^     
     ^^^^^^^^^^^^^^^^     
    ^^^^^^^^^^^^^^^^^    
    ^^^^^^^^^^^^^^^^^^    
   ^^^^^^^^^^^^^^^^^^^   
   ^^^^^^^^^^^^^^^^^^^^   
  ^^^^^^^^^^^^^^^^^^^^^  
  ^^^^^^^^^^^^^^^^^^^^^^  
                        
            ^            
           ^^           
           ^^^           
          ^^^^          
          ^^^^^          
         ^^^^^^         
         ^^^^^^^         
        ^^^^^^^^        
        ^^^^^^^^^        
           ^^^           
          ^^^^          
          ^^^^^          
         ^^^^^^         
         ^^^^^^^         
        ^^^^^^^^        
        ^^^^^^^^^        
       ^^^^^^^^^^       
       ^^^^^^^^^^^       
      ^^^^^^^^^^^^      
         ^^^^^^         
         ^^^^^^^         
        ^^^^^^^^        
        ^^^^^^^^^        
       ^^^^^^^^^^       
       ^^^^^^^^^^^       
      ^^^^^^^^^^^^      
      ^^^^^^^^^^^^^      
     ^^^^^^^^^^^^^^     
     ^^^^^^^^^^^^^^^     
        ^^^^^^^^^        
       ^^^^^^^^^^       
       ^^^^^^^^^^^       
      ^^^^^^^^^^^^      
      ^^^^^^^^^^^^^      
     ^^^^^^^^^^^^^^     
     ^^^^^^^^^^^^^^^     
    ^^^^^^^^^^^^^^^^    
    ^^^^^^^^^^^^^^^^^    
   ^^^^^^^^^^^^^^^^^^   
      ^^^^^^^^^^^^      
      ^^^^^^^^^^^^^      
     ^^^^^^^^^^^^^^     
     ^^^^^^^^^^^^^^^     
    ^^^^^^^^^^^^^^^^    
    ^^^^^^^^^^^^^^^^^    
   ^^^^^^^^^^^^^^^^^^   
   ^^^^^^^^^^^^^^^^^^^   
  ^^^^^^^^^^^^^^^^^^^^  
  ^^^^^^^^^^^^^^^^^^^^^  
                
        ^        
       ^^       
       ^^^       
      ^^^^      
      ^^^^^      
     ^^^^^^     
     ^^^^^^^     
       ^^^       
      ^^^^      
      ^^^^^      
     ^^^^^^     
     ^^^^^^^     
    ^^^^^^^^    
    ^^^^^^^^^    
   ^^^^^^^^^^   
     ^^^^^^     
     ^^^^^^^     
    ^^^^^^^^    
    ^^^^^^^^^    
   ^^^^^^^^^^   
   ^^^^^^^^^^^   
  ^^^^^^^^^^^^  
  ^^^^^^^^^^^^^  


Write a function called generate_square_numbers. This takes one argument named num, which specified how many square numbers to generate. This function will print out the first num square numbers, starting from 1, one number per line of stdout.

For example, when num is 6 it would produce:

1
4
9
16
25
36

When num is 10 it would produce:

1
4
9
16
25
36
49
64
81
100