The Friendly Python

Lesson 3: Control Structures

A Taste Of Programming
Lesson: 1 2 3 4 5

Mississippi College

Computer Science 114

This lesson covers some of Python's control constructs. Control constructs control the execution of other parts of a program. They allow portions to be skipped or repeated, depending on the input data. We will cover only a bit of this rather broad topic.

  1. As before, open Idle.

  2. Sometimes a program needs to test a variable, and take different action depending on its value. Here's a simple example:

    # Python affinity test I
    response = raw_input("Do you like Python? (yes/no) ")
    if response == 'yes':
        print "----------------------------------"
        print "Of course.  Everyone likes Python."
        print "----------------------------------"
    else:
        print "Excuse me, I must have mis-heard you.  It sounded like", response
    print "bye, now."
    Enter this program and run it a few times. Make sure to elicit both answers.

    There are several things to notice about this program.

    • The if construct tells Python to make a decision. The if keyword is followed by some condition Python can test for truth or falsity. The test must be followed by a colon. This particular test simply decides if two expressions are the same, specifically if the value of response is the string 'yes'.
    • When the test is true, the group if statements immediately after the colon is executed; if the test is false, the group of statements following else: is executed instead. The other group of statements is skipped. The two groups are called branches; the first being the true branch, and the second the false branch.
    • The statements within the branch must be indented by the same amount. This tells python which statements belong to the branches.*
    • The last print is not indented. Therefore it is outside the if and is always run.

    Here is the reason why it was an error to place spaces before your expression on Lesson 1: Python thinks indented statements are part of an if, or some other control construct. When no such construct exists, Python gets very upset.

  3. The == in the last example is a comparison operator. Python uses == for comparison since = is already used for assignment. Here's the set of them:
    a == b Check that a equals b.
    a != b Check that a does not equal b.
    a < b Check that a is strictly less than b.
    a <= b Check that a is less than or equal b.
    a > b Check that a is strictly greater than b.
    a >= b Check that a is greater than or equal b.

    We've discussed some of Python's data types: integer, floating point, and string. Comparisons return another type: boolean. The boolean type has only two possible values: True and False. Try some of these from the Python command line:

    >>> 5 == 5
    True
    >>> 12 < 18
    True
    >>> -3.4 >= 9.3
    False
    >>> "Fred" == "Barney"
    False
    >>> "alpha" < "beta"
    True
    >>> 

    Generally, comparisons are used to compare similar types: numbers to numbers, strings to strings, etc. When comparing strings to strings, the inequalities compare using an odd sort of alphabetical order, where all the upper case letters come before all the lower case ones. Using this peculiar ordering, the < operator means "comes before".

    >>> "alpha" < "beta"
    True
    >>> "Tom" <= "Jerry"
    False
    >>> "Tom" <= "jerry"
    True
    >>> "tom" <= "jerry"
    False
    >>> "tom" <= "Jerry"
    False
    >>> "TOM" == "tom"
    False
    >>> "TOM" == "TOM"
    True
    >>> 

    Also note that the values compared may be any other expressions, as:

    >>> 5 == 2 + 3
    True
    >>> joe = 99
    >>> joe / 3 > 10
    True
    >>> 5 * joe < 6 * joe - 100
    False
    >>> 
    Run some comparisons from the Python command line to see how they work. Note that if you compare different types of values (apples to oranges), Python will not signal an error, but instead will give you an answer making as little sense as the question.

  4. Boolean values can also be combined using the boolean operators and and or. These each take two booleans, and produce a boolean result. And produces true when both inputs are true; false otherwise. Or produces true when at least one of its inputs is true; false otherwise.¤ What does that add up to? Probably just what you were expecting:

    >>> 5 < 6 and 19 == 19
    True
    >>> frank = 34
    >>> frank == 9 or frank == 34
    True
    >>> frank == 10 or frank > 40
    False
    >>> bill = "Howdy"
    >>> bill[1] == 'o' and frank > 10 and frank < 40
    True
    >>> bill[2] == 'p' and frank > 10 and frank < 40
    False
    >>> bill[2] == 'p' and frank > 10 or frank < 40
    True
    >>> bill[2] == 'p' and (frank > 10 or frank < 40)
    False
    >>> 
    The last one shows that Python evaluates and before or, but we can change the order using parentheses, just as we might with a numerical expression such as 5 * (6 + 7). Try a few.

  5. Python's if can get quite complex. For one thing, the else part may be omitted entirely, in which case it does nothing after finding the test false. Also, since the branches of an if may contain any other Python statements, they may contain other if's. This is called nesting. On top of all that, Python's if statements may be extended to check several conditions. Here's an improved version of the last program:

    # Python affinity test II
    response = raw_input("Do you like Python? (y/n) ")
    if response[0] == 'y' or response[0] == 'Y':
        print "----------------------------------"
        print "Of course.  Everyone likes Python."
        print "----------------------------------"
        response = raw_input("Do you like it a WHOLE LOT!!! (YES/no) ")
        if response == 'YES':
            print 'huRAH!!!'
    elif response[0] == 'n' or response[0] == 'N':
        print "Excuse me, I must have mis-heard you.  It sounded like 'no'."
    else:
        print "Please say 'yes' or 'no'."
    print "bye, now."
    Modify your program to look like this silly thing, and run it several times to get all messages out. Make sure you understand what makes the program generate each response. The elif keyword is an abbreviation for else if.

  6. Another important class of control constructs is repetition, also called looping. This simply means to repeat some section of code several times. Python has two looping statements, while and for, but we'll limit ourselves to the for loop. Here's a simple example:

    for n in [4, 12, -3, 7]:
        print n
    Open a new window, enter this as a program (all two line), save it, and run it.

    The for statement just repeats a range of statements (the loop body) once for each element in the list, in order. Before running the body each time (before each iteration), the for loop sets an index variable to the appropriate list value. In this example, the index variable is n, but any variable may be used. As with the if, the for statement ends with a colon, and the body statements are indented.

    In the above example, we gave an explicit list enclosed in brackets, but there are some other ways to make lists:

    # Useless count
    for n in range(3, 7):
        print "Number", n

    # Letter counter
    count = 1
    for ch in "Friday":
        print "Letter", count, "is", ch
        count = count + 1
    Enter and run this beast, and see what happens. In the first loop, we use the range function to create our list. The range has a peculiarity similar to the substring slice notation: it goes up to, but excludes, the second number.

    The second example shows that we can use a string as a list of its characters. It also demonstrates a common programming idiom: Using a counter inside a loop. The counter count is set to 1 before the loop starts, the initialization. Each iteration of the loop runs the statement count = count + 1, which increases the value of count by one. This is the increment. Look at the output to see how the values of count change for each iteration.

  7. Since any statement may be placed in a loop body, we can nest ifs or other loops within loops. For instance:

    # Space counter
    line = raw_input("Enter one line: ")
    nchar = 0
    num_sp = 0
    for ch in line:
        if ch == ' ':
            num_sp = num_sp + 1
        nchar = nchar + 1
    print "You entered:", line
    print "  That line contains", nchar, 'characters, including', num_sp, 'spaces.'
    Please enter this program, run it a few times, and look at the output. Now we have one counter, nchar, which is incremented for each character in the input string, and num_sp which is incremented only for those characters (spaces) that it wants to count. Each counter represents the number of characters seen so far: it starts at zero, and increases for each interesting character in the input string. When the loop finishes, the counts are correct for the whole input string.

    A. One More Time!

    1. Extend the previous character counter so that it also counts the number of E's in the input string. Include both the upper and lower case forms in your count.
    2. Create a similar program which reports two counts, one of upper case and one of lower case letters.
      Enter one line: This is a line.
      You entered:  This is a line.
        This line has 1 upper case, and 10 lower case letters.
      You can identify a character as upper case if it is greater than or equal to 'A', and also less than or equal to 'Z'. Likewise, lower case letters will be between 'a' and 'z'.

  8. The above example loops count something. Counting is a kind of accumulation: each iteration adds something to the counter. It's also possible to accumulate strings. Here's one:

    # Dash for space
    line = raw_input("Please enter yet another line: ")
    result = ''
    for c in line:
        if c == ' ':
            result = result + '-'
        else:
            result = result + c
    print "Now we have:", result
    Enter it and run it. As you can see, it replaces each space in your input with a dash. The loop walks through the input characters and uses result to accumulate the output line. Result is initialized to the empty string, and each iteration adds one character. For an input space, it adds a dash, otherwise it adds the input character. The result is almost a copy of the input line, except for the spaces.

    B. Build One For Me

    1. Modify the above program to simply remove all the spaces. The input Hi there, Fred! becomes Hithere,Fred!.
    2. Make a similar program which prints the output backward. The input Hi there, Fred! becomes !derF ,ereht iH. To do this, concatenate the characters in reverse order. You won't need an if in your loop for this one.
    3. Optional: Create a program which inputs a string and outputs each letter an increasing number of times. The first character is output once, the second twice, the third three times, etc. For instance, the input Howdy! becomes Hoowwwddddyyyyy!!!!!!. For this, you will want to add an integer counter to your loop, and remember what * does when applied to a string and an integer.

  9. Most programming languages support some idea of a function or a procedure. We have used built-in Python functions, but Python also lets programmers to create their own. Here's an example:

    # Return the larger
    def larger(a, b):
        if a > b:
            return a
        else:
            return b

    tom = int(raw_input("Please enter an integer: "))
    jane = int(raw_input("Please enter another integer: "))
    spot = int(raw_input("Please enter still another integer: "))
    print "The larger of", tom, "and", jane, "is", larger(tom,jane)
    print "The larger of", jane - 5 , "and", 3*spot, "is", larger(jane - 5,3*spot)
    print "The smaller of", tom, "and", spot, "is", -larger(-tom, -spot)
    print "The largest of", tom, jane, "and", spot, "is", larger(larger(tom,jane),spot)
    Please enter this beast and run it. The function larger takes two values, figures out which one is larger, and returns it to the caller.

    As you can see, a Python function definition starts with the word def, followed by the the name of the function, then a list of parameter names enclosed in parentheses and separated by commas. Parameters are variable names used to pass values into the function; you may use any legal variable names, and you may have number of parameters. The parameter list is followed by a colon. As before, the body of the function is a group of indented statements. A function body may contain any of the regular Python statements, plus the return statement.

    A function can be used in any Python expression, as larger is used in the print statements. This is known as calling the function. In a call, the function name is followed by a list of arguments in parentheses. Each argument is an expression, and the number of arguments must equal the number of parameters. The value of each argument is assigned to the corresponding parameter, then the function body is run. When the function body executes a return statement, the value it specifies becomes the value of the function call. This value is returned to the expression as the value of the function call.

    For instance, consider the second print statement,

    print "The larger of", jane - 5 , "and", 3*spot, "is", larger(jane - 5,3*spot)
    Assume that jane is 8 and spot is 12. Python will:
    • Evaluate each argument expression, yielding 3 and 36.
    • Assign parameter a the value 3 and b the value 36.
    • Execute the body, with these values. Since the if test will be false, the function will execute return b, where b is 36.
    • The 36 is returned to the print statement as the value of the function call, where it is printed.

    The function larger shortens this example program considerably. The function is called in five places. If each of those calls were replaced with the code to perform the function, the program would be considerably larger, and harder to understand. Those are two major reasons why programmers use functions. Another reason is to simplify the design process.

    Any complex system is designed using subassemblies. An engineer who designs an automobile does not start organizing sheet metal and bolts into an automobile. He organizes the problem into subassemblies. Major subassemblies of an automobile are the engine, transmission, the suspension system, etc. Each of these subassemblies is further decomposed into smaller bits. The car is designed of large subassemblies, each of which is designed from smaller sub-subassemblies and so forth, until we finally get down to nuts, bolts and sheet metal. Functions provide the subassemblies a programmer uses to organize a complex program. The problem is divided into sub-steps, which are implemented in functions. These may call other functions, working down to individual statements in a program.

  10. Enter and run this beast:

    # Display one char of a string as part of a small hill.
    def drline(string, position):
        if position < len(string) / 2:
            count = 2*position + 1
        else:
            count = 2*(len(string) - position) - 1
        print '-' * count, string[position]

    # Request and print a string.
    str = raw_input('Hey, there, throw us a string, man! ')

    print
    for p in range(0, len(str)):
        drline(str, p)
    This example demonstrates a number of things.
    • I need to get out more.
    • Not every function needs to execute a return. When they don't they are called as you see here, in a statement alone, but not as part of a larger expression. Some programming languages sensibly refer to functions of these type as procedures rather than functions, but in Python they're all called functions.
    • Functions can use variables other than the parameters. These variables are local to the function. If you try to refer to one outside the function body, Python will tell you that it is undefined.
    • Since this function is called from only one place, it does not shorten the program. But it does make the program easier to create. When the programmer writes drline, he doesn't need to think about the whole program, just about what to do to generate one particular line of output. When the programmer creates the main part of the program which uses the function, he need only think about reading the string and looping through, and the fact that we'll have to do something called drline for each character.

    C. Form The Functions

    1. Create a function which takes three parameters and returns their average as a floating point number. Place it in a Python program which will read inputs for it and print the result.
    2. Take the print statements from the madlib program from Lesson 2. Make a function which takes the various words as parameters and prints the madlib with those values. Put it into a Python program that simply prints the madlib three times with different values. Don't take input values; just print. Your program will produce the same output each time.
    3. Create a function genline which creates and returns a string. It takes three parameters: the length of the string (which must be at least 2), an end character, and a content character. It returns a string of the specified length starting and ending with the end character. For instance, genline(9, "@", "=") returns "@=======@". Place it in a Python program which calls genline with various parameters and prints the result so you can see it work.
    4. Create another program using genline. It should request a width and a height and produce a box, as follows:
      Please enter the box width: 8
      Please enter the box height: 5
      +------+
      |      |
      |      |
      |      |
      +------+
      The box in the example is eight wide and five tall as requested, though it looks closer to square because characters are taller than they are wide. In mine, I called genline in three places, one for the top line, once in a loop to generate the middle lines, and once for the final line. Don't forget that space (' ')is a perfectly good character to send send to genline.

Now our programs can condition or repeat code as required by the input. Functions allow use to separate out parts for design or reuse. This gives us enough tools to do a bit more. So far, our programs have been text-based: all typing. In Lesson 4, we'll modify images, and in Lesson 5 we'll take a look at GUIs.


*This indenting rule is peculiar to Python. Most languages use keywords or special symbols to delimit a block of controlled statements.

For mathematician George Boole, who studied mathematical systems of this type.

The order actually comes from the character coding. Each character is assigned an arbitrary numerical code value. Characters are recorded by storing this code value in the computer's memory. The comparison operators simply compare the codes. It's sort of like having the class line up in order by Social Security number. The assignments are arbitrary, but most computers follow the ASCII coding standard so that they can all be arbitrary in the same way.

¤It's actually a little more complicated than that. If you care, look here.


Copyright 2005, 2006 Thomas W Bennet  •  Image Credits  •  Terms of use: Creative Commons