Monday, 6 March 2017

Boolean Expressions - python (part 10)

Boolean Expressions

Here is a little example of boolean expressions (you don't have to type it in):
a = 6
b = 7
c = 42
print 1, a == 6
print 2, a == 7
print 3, a == 6 and b == 7
print 4, a == 7 and b == 7
print 5, not a == 7 and b == 7
print 6, a == 7 or b == 7
print 7, a == 7 or b == 6
print 8, not (a == 7 and b == 6)
print 9, not a == 7 and b == 6
With the output being:
1 True
2 False
3 True
4 False
5 True
6 True
7 False
8 True
9 False
What is going on? The program consists of a bunch of funny looking print statements. Each print statement prints a number and an expression. The number is to help keep track of which statement I am dealing with. Notice how each expression ends up being either False or True. In Python, false can also be written as 0 and true as 1.
The lines:
print 1, a == 6
print 2, a == 7
print out a True and a False respectively just as expected since the first is true and the second is false. The third print, print 3, a == 6 and b == 7, is a little different. The operator and means if both the statement before and the statement after are true then the whole expression is true otherwise the whole expression is false. The next line,print 4, a == 7 and b == 7, shows how if part of an and expression is false, the whole thing is false. The behavior of and can be summarized as follows:
expression result
true and true true
true and false false
false and true false
false and false false
Notice that if the first expression is false Python does not check the second expression since it knows the whole expression is false.
The next line, print 5, not a == 7 and b == 7, uses the not operator. not just gives the opposite of the expression. (The expression could be rewritten as print 5, a != 7 and b == 7). Here is the table:
expression result
not true false
not false true
The two following lines, print 6, a == 7 or b == 7 and print 7, a == 7 or b == 6, use the or operator. The or operator returns true if the first expression is true, or if the second expression is true or both are true. If neither are true it returns false. Here's the table:
expression result
true or true true
true or false true
false or true true
false or false false
Notice that if the first expression is true Python doesn't check the second expression since it knows the whole expression is true. This works since or is true if at least one half of the expression is true. The first part is true so the second part could be either false or true, but the whole expression is still true.
The next two lines, print 8, not (a == 7 and b == 6) and print 9, not a == 7 and b == 6, show that parentheses can be used to group expressions and force one part to be evaluated first. Notice that the parentheses changed the expression from false to true. This occurred since the parentheses forced the not to apply to the whole expression instead of just the a == 7 portion.
Here is an example of using a boolean expression:
list = ["Life", "The Universe", "Everything", "Jack", "Jill", "Life", "Jill"]

# make a copy of the list. See the More on Lists chapter to explain what [:] means.
copy = list[:]
# sort the copy
copy.sort()
prev = copy[0]
del copy[0]

count = 0

# go through the list searching for a match
while count < len(copy) and copy[count] != prev:
    prev = copy[count]
    count = count + 1

# If a match was not found then count can't be < len
# since the while loop continues while count is < len
# and no match is found

if count < len(copy):
    print "First Match:", prev
And here is the output:
First Match: Jill
This program works by continuing to check for match while count < len(copy) and copy[count] is not equal to prev. When either count is greater than the last index of copy or a match has been found the and is no longer true so the loop exits. The if simply checks to make sure that the while exited because a match was found.
The other "trick" of and is used in this example. If you look at the table for and notice that the third entry is "false and won't check". If count >= len(copy) (in other wordscount < len(copy) is false) then copy[count] is never looked at. This is because Python knows that if the first is false then they can't both be true. This is known as a short circuit and is useful if the second half of the and will cause an error if something is wrong. I used the first expression (count < len(copy)) to check and see if count was a valid index for copy. (If you don't believe me remove the matches "Jill" and "Life", check that it still works and then reverse the order of count < len(copy) and copy[count] != prev to copy[count] != prev and count < len(copy).)
Boolean expressions can be used when you need to check two or more different things at once.
A note on Boolean Operators
A common mistake for people new to programming is a misunderstanding of the way that boolean operators works, which stems from the way the python interpreter reads these expressions. For example, after initially learning about "and " and "or" statements, one might assume that the expression x == ('a' or 'b') would check to see if the variablex was equivalent to one of the strings 'a' or 'b'. This is not so. To see what I'm talking about, start an interactive session with the interpreter and enter the following expressions:
>>> 'a' == ('a' or 'b')
>>> 'b' == ('a' or 'b')
>>> 'a' == ('a' and 'b')
>>> 'b' == ('a' and 'b')
And this will be the unintuitive result:
>>> 'a' == ('a' or 'b')
True
>>> 'b' == ('a' or 'b')
False
>>> 'a' == ('a' and 'b')
False
>>> 'b' == ('a' and 'b')
True
At this point, the and and or operators seem to be broken. It doesn't make sense that, for the first two expressions, 'a' is equivalent to 'a' or 'b' while 'b' is not. Furthermore, it doesn't make any sense that 'b' is equivalent to 'a' and 'b'. After examining what the interpreter does with boolean operators, these results do in fact exactly what you are asking of them, it's just not the same as what you think you are asking.
When the Python interpreter looks at an or expression, it takes the first statement and checks to see if it is true. If the first statement is true, then Python returns that object's value without checking the second statement. This is because for an or expression, the whole thing is true if one of the values is true; the program does not need to bother with the second statement. On the other hand, if the first value is evaluated as false Python checks the second half and returns that value. That second half determines the truth value of the whole expression since the first half was false. This "laziness" on the part of the interpreter is called "short circuiting" and is a common way of evaluating boolean expressions in many programming languages.
Similarly, for an and expression, Python uses a short circuit technique to speed truth value evaluation. If the first statement is false then the whole thing must be false, so it returns that value. Otherwise if the first value is true it checks the second and returns that value.
One thing to note at this point is that the boolean expression returns a value indicating True or False, but that Python considers a number of different things to have a truth value assigned to them. To check the truth value of any given object x, you can use the function bool(x) to see its truth value. Below is a table with examples of the truth values of various objects:
True False
True False
1 0
Numbers other than zero The string 'None'
Nonempty strings Empty strings
Nonempty lists Empty lists
Nonempty dictionaries Empty dictionaries
Now it is possible to understand the perplexing results we were getting when we tested those boolean expressions before. Let's take a look at what the interpreter "sees" as it goes through that code:
First case:
>>> 'a' == ('a' or 'b')  # Look at parentheses first, so evaluate expression "('a' or 'b')"
                           # 'a' is a nonempty string, so the first value is True
                           # Return that first value: 'a'
>>> 'a' == 'a'           # the string 'a' is equivalent to the string 'a', so expression is True
True
Second case:
>>> 'b' == ('a' or 'b')  # Look at parentheses first, so evaluate expression "('a' or 'b')"
                           # 'a' is a nonempty string, so the first value is True
                           # Return that first value: 'a'
>>> 'b' == 'a'           # the string 'b' is not equivalent to the string 'a', so expression is False
False
Third case:
>>> 'a' == ('a' and 'b') # Look at parentheses first, so evaluate expression "('a' and 'b')"
                           # 'a' is a nonempty string, so the first value is True, examine second value
                           # 'b' is a nonempty string, so second value is True
                           # Return that second value as result of whole expression: 'b'
>>> 'a' == 'b'           # the string 'a' is not equivalent to the string 'b', so expression is False
False
Fourth case:
>>> 'b' == ('a' and 'b') # Look at parentheses first, so evaluate expression "('a' and 'b')"
                           # 'a' is a nonempty string, so the first value is True, examine second value
                           # 'b' is a nonempty string, so second value is True
                           # Return that second value as result of whole expression: 'b'
>>> 'b' == 'b'           # the string 'b' is equivalent to the string 'b', so expression is True
True
So Python was really doing its job when it gave those apparently bogus results. As mentioned previously, the important thing is to recognize what value your boolean expression will return when it is evaluated, because it isn't always obvious.
Going back to those initial expressions, this is how you would write them out so they behaved in a way that you want:
>>> 'a' == 'a' or 'a' == 'b'
True
>>> 'b' == 'a' or 'b' == 'b'
True
>>> 'a' == 'a' and 'a' == 'b'
False
>>> 'b' == 'a' and 'b' == 'b'
False
When these comparisons are evaluated they return truth values in terms of True or False, not strings, so we get the proper results.

print "Try to guess my name!"
count = 0
name = "Tony"
guess = raw_input("What is my name? ")
while count < 3 and guess != name:
    print "You are wrong!"
    guess = raw_input("What is my name? ")
    count = count + 1

if guess != name:
    print "You are wrong!" # this message isn't printed in the third chance, so we print it now
    print "You ran out of chances."
    quit
else:
    print "Yes! My name is", name + "!"

For Loops - python (part 9)

For Loops

And here is the new typing exercise for this chapter:
onetoten = range(1, 11)
for count in onetoten:
    print count
and the ever-present output:
1
2
3
4
5
6
7
8
9
10
The output looks awfully familiar but the program code looks different. The first line uses the range function. The range function uses two arguments like this range(start, finish). start is the first number that is produced. finish is one larger than the last number. Note that this program could have been done in a shorter way:
for count in range(1, 11):
    print count
Here are some examples to show what happens with the range command:
>>> range(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(-32, -20)
[-32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21]
>>> range(5,21)
[5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
>>> range(5)
[0, 1, 2, 3, 4]
>>> range(21, 5)
[]
The next line for count in onetoten: uses the for control structure. A for control structure looks like for variable in list:. list is gone through starting with the first element of the list and going to the last. As for goes through each element in a list it puts each into variable. That allows variable to be used in each successive time the for loop is run through. Here is another example (you don't have to type this) to demonstrate:
demolist = ['life', 42, 'the universe', 6, 'and', 9, 'everything']
for item in demolist:
    print "The Current item is:",
    print item
The output is:
The Current item is: life
The Current item is: 42
The Current item is: the universe
The Current item is: 6
The Current item is: and
The Current item is: 9
The Current item is: everything
Notice how the for loop goes through and sets item to each element in the list. Notice how if you don't want print to go to the next line add a comma at the end of the statement (i.e. if you want to print something else on that line). So, what is for good for? The first use is to go through all the elements of a list and do something with each of them. Here's a quick way to add up all the elements:
list = [2, 4, 6, 8]
sum = 0
for num in list:
    sum = sum + num

print "The sum is:", sum
with the output simply being:
The sum is: 20
Or you could write a program to find out if there are any duplicates in a list like this program does:
list = [4, 5, 7, 8, 9, 1, 0, 7, 10]
list.sort()
prev = list[0]
del list[0]
for item in list:
    if prev == item:
        print "Duplicate of", prev, "found"
    prev = item
and for good measure:
Duplicate of 7 Found
Okay, so how does it work? Here is a special debugging version to help you understand (you don't need to type this in):
l = [4, 5, 7, 8, 9, 1, 0, 7, 10]
print "l = [4, 5, 7, 8, 9, 1, 0, 7, 10]", "\t\tl:", l
l.sort()
print "l.sort()", "\t\tl:", l
prev = l[0]
print "prev = l[0]", "\t\tprev:", prev
del l[0]
print "del l[0]", "\t\tl:", l
for item in l:
    if prev == item:
        print "Duplicate of", prev, "found"
    print "if prev == item:", "\t\tprev:", prev, "\titem:", item
    prev = item
    print "prev = item", "\t\tprev:", prev, "\titem:", item
with the output being:
l = [4, 5, 7, 8, 9, 1, 0, 7, 10]        l: [4, 5, 7, 8, 9, 1, 0, 7, 10]
l.sort()                l: [0, 1, 4, 5, 7, 7, 8, 9, 10]
prev = l[0]             prev: 0
del l[0]                l: [1, 4, 5, 7, 7, 8, 9, 10]
if prev == item:        prev: 0         item: 1
prev = item             prev: 1         item: 1
if prev == item:        prev: 1         item: 4
prev = item             prev: 4         item: 4
if prev == item:        prev: 4         item: 5
prev = item             prev: 5         item: 5
if prev == item:        prev: 5         item: 7
prev = item             prev: 7         item: 7
Duplicate of 7 found
if prev == item:        prev: 7         item: 7
prev = item             prev: 7         item: 7
if prev == item:        prev: 7         item: 8
prev = item             prev: 8         item: 8
if prev == item:        prev: 8         item: 9
prev = item             prev: 9         item: 9
if prev == item:        prev: 9         item: 10
prev = item             prev: 10        item: 10
The reason I put so many print statements in the code was so that you can see what is happening in each line. (By the way, if you can't figure out why a program is not working, try putting in lots of print statements so you can see what is happening.) First the program starts with a boring old list. Next the program sorts the list. This is so that any duplicates get put next to each other. The program then initializes a prev(ious) variable. Next the first element of the list is deleted so that the first item is not incorrectly thought to be a duplicate. Next a for loop is gone into. Each item of the list is checked to see if it is the same as the previous. If it is a duplicate was found. The value of prev is then changed so that the next time the for loop is run through prev is the previous item to the current. Sure enough, the 7 is found to be a duplicate. (Notice how \t is used to print a tab.)
The other way to use for loops is to do something a certain number of times. Here is some code to print out the first 9 numbers of the Fibonacci series:
a = 1
b = 1
for c in range(1, 10):
    print a,
    n = a + b
    a = b
    b = n
with the surprising output:
1 1 2 3 5 8 13 21 34
Everything that can be done with for loops can also be done with while loops but for loops give an easy way to go through all the elements in a list or to do something a certain number of times.

List - python (part 8)

Lists

Variables with more than one value
You have already seen ordinary variables that store a single value. However other variable types can hold more than one value. The simplest type is called a list. Here is an example of a list being used:
which_one = input("What month (1-12)? ")
months = ['January', 'February', 'March', 'April', 'May', 'June', 'July',
          'August', 'September', 'October', 'November', 'December']

if 1 <= which_one <= 12:
    print "The month is", months[which_one - 1]
and an output example:
What month (1-12)? 3
The month is March
In this example the months is a list. months is defined with the lines months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', and'August', 'September', 'October', 'November', 'December'] (note that a \ could also be used to split a long line, but that is not necessary in this case because Python is intelligent enough to recognize that everything within brackets belongs together). The [ and ] start and end the list with commas (,) separating the list items. The list is used in months[which_one - 1]. A list consists of items that are numbered starting at 0. In other words if you wanted January you would use months[0]. Give a list a number and it will return the value that is stored at that location.
The statement if 1 <= which_one <= 12: will only be true if which_one is between one and twelve inclusive (in other words it is what you would expect if you have seen that in algebra).
Lists can be thought of as a series of boxes. Each box has a different value. For example, the boxes created by demolist = ['life', 42, 'the universe', 6, 'and', 7] would look like this:
box number 0 1 2 3 4 5
demolist "life" 42 "the universe" 6 "and" 7
Each box is referenced by its number so the statement demolist[0] would get 'life', demolist[1] would get 42 and so on up to demolist[5] getting 7.
More features of lists
The next example is just to show a lot of other stuff lists can do (for once I don't expect you to type it in, but you should probably play around with lists until you are comfortable with them.). Here goes:
demolist = ["life", 42, "the universe", 6, "and", 7]
print "demolist = ",demolist
demolist.append("everything")
print "after 'everything' was appended demolist is now:"
print demolist
print "len(demolist) =", len(demolist)
print "demolist.index(42) =", demolist.index(42)
print "demolist[1] =", demolist[1]

# Next we will loop through the list
c = 0
while c < len(demolist):
    print "demolist[", c, "] =", demolist[c]
    c = c + 1

del demolist[2]
print "After 'the universe' was removed demolist is now:"
print demolist
if "life" in demolist:
    print "'life' was found in demolist"
else:
    print "'life' was not found in demolist"

if "amoeba" in demolist:
    print "'amoeba' was found in demolist"

if "amoeba" not in demolist:
    print "'amoeba' was not found in demolist"

demolist.sort()
print "The sorted demolist is", demolist
The output is:
demolist =  ['life', 42, 'the universe', 6, 'and', 7]
after 'everything' was appended demolist is now:
['life', 42, 'the universe', 6, 'and', 7, 'everything']
len(demolist) = 7
demolist.index(42) = 1
demolist[1] = 42
demolist[ 0 ] = life
demolist[ 1 ] = 42
demolist[ 2 ] = the universe
demolist[ 3 ] = 6
demolist[ 4 ] = and
demolist[ 5 ] = 7
demolist[ 6 ] = everything
After 'the universe' was removed demolist is now:
['life', 42, 6, 'and', 7, 'everything']
'life' was found in demolist
'amoeba' was not found in demolist
The sorted demolist is [6, 7, 42, 'and', 'everything', 'life']
This example uses a whole bunch of new functions. Notice that you can just print a whole list. Next the append function is used to add a new item to the end of the list. lenreturns how many items are in a list. The valid indexes (as in numbers that can be used inside of the []) of a list range from 0 to len - 1. The index function tells where the first location of an item is located in a list. Notice how demolist.index(42) returns 1, and when demolist[1] is run it returns 42. The line # Next we will loop through the list is a just a reminder to the programmer (also called a comment). Python will ignore any lines that start with a #. Next the lines:
c = 0
while c < len(demolist):
    print 'demolist[', c, '] =', demolist[c]
    c = c + 1
create a variable c, which starts at 0 and is incremented until it reaches the last index of the list. Meanwhile the print statement prints out each element of the list. The delcommand can be used to remove a given element in a list. The next few lines use the in operator to test if an element is in or is not in a list. The sort function sorts the list. This is useful if you need a list in order from smallest number to largest or alphabetical. Note that this rearranges the list. In summary, for a list, the following operations occur:
example explanation
demolist[2] accesses the element at index 2
demolist[2] = 3 sets the element at index 2 to be 3
del demolist[2] removes the element at index 2
len(demolist) returns the length of demolist
"value" in demolist is True if "value" is an element in demolist
"value" not in demolist is True if "value" is not an element in demolist
demolist.sort() sorts demolist
demolist.index("value") returns the index of the first place that "value" occurs
demolist.append("value") adds an element "value" at the end of the list
demolist.remove("value") removes the first occurrence of value from demolist (same as del demolist[demolist.index("value")])
This next example uses these features in a more useful way:
menu_item = 0
namelist = []
while menu_item != 9:
    print "--------------------"
    print "1. Print the list"
    print "2. Add a name to the list"
    print "3. Remove a name from the list"
    print "4. Change an item in the list"
    print "9. Quit"
    menu_item = input("Pick an item from the menu: ")
    if menu_item == 1:
        current = 0
        if len(namelist) > 0:
            while current < len(namelist):
                print current, ".", namelist[current]
                current = current + 1
        else:
            print "List is empty"
    elif menu_item == 2:
        name = raw_input("Type in a name to add: ")
        namelist.append(name)
    elif menu_item == 3:
        del_name = raw_input("What name would you like to remove: ")
        if del_name in namelist:
            # namelist.remove(del_name) would work just as fine
            item_number = namelist.index(del_name)
            del namelist[item_number]
            # The code above only removes the first occurrence of
            # the name.  The code below from Gerald removes all.
            # while del_name in namelist:
            #       item_number = namelist.index(del_name)
            #       del namelist[item_number]
        else:
            print del_name, "was not found"
    elif menu_item == 4:
        old_name = raw_input("What name would you like to change: ")
        if old_name in namelist:
            item_number = namelist.index(old_name)
            new_name = raw_input("What is the new name: ")
            namelist[item_number] = new_name
        else:
            print old_name, "was not found"

print "Goodbye"
And here is part of the output:
--------------------
1. Print the list
2. Add a name to the list
3. Remove a name from the list
4. Change an item in the list
9. Quit

Pick an item from the menu: 2
Type in a name to add: Jack

Pick an item from the menu: 2
Type in a name to add: Jill

Pick an item from the menu: 1
0 . Jack
1 . Jill

Pick an item from the menu: 3
What name would you like to remove: Jack

Pick an item from the menu: 4
What name would you like to change: Jill
What is the new name: Jill Peters

Pick an item from the menu: 1
0 . Jill Peters

Pick an item from the menu: 9
Goodbye
That was a long program. Let's take a look at the source code. The line namelist = [] makes the variable namelist a list with no items (or elements). The next important line is while menu_item != 9:. This line starts a loop that allows the menu system for this program. The next few lines display a menu and decide which part of the program to run.
The section
current = 0
if len(namelist) > 0:
    while current < len(namelist):
        print current, ".", namelist[current]
        current = current + 1
else:
    print "List is empty"
goes through the list and prints each name. len(namelist) tells how many items are in the list. If len returns 0, then the list is empty.
Then, a few lines later, the statement namelist.append(name) appears. It uses the append function to add an item to the end of the list. Jump down another two lines, and notice this section of code:
item_number = namelist.index(del_name)
del namelist[item_number]
Here the index function is used to find the index value that will be used later to remove the item. del namelist[item_number] is used to remove a element of the list.
The next section
old_name = raw_input("What name would you like to change: ")
if old_name in namelist:
    item_number = namelist.index(old_name)
    new_name = raw_input("What is the new name: ")
    namelist[item_number] = new_name
else:
   print old_name, "was not found"
uses index to find the item_number and then puts new_name where the old_name was.
Congratulations, with lists under your belt, you now know enough of the language that you could do any computations that a computer can do (this is technically known as Turing-Completeness). Of course, there are still many features that are used to make your life easier.
Examples
test.py
## This program runs a test of knowledge

# First get the test questions
# Later this will be modified to use file io.
def get_questions():
    # notice how the data is stored as a list of lists
    return [["What color is the daytime sky on a clear day? ", "blue"],
            ["What is the answer to life, the universe and everything? ", "42"],
            ["What is a three letter word for mouse trap? ", "cat"]]

# This will test a single question
# it takes a single question in
# it returns True if the user typed the correct answer, otherwise False

def check_question(question_and_answer):
    # extract the question and the answer from the list
    question = question_and_answer[0]
    answer = question_and_answer[1]
    # give the question to the user
    given_answer = raw_input(question)
    # compare the user's answer to the testers answer
    if answer == given_answer:
        print "Correct"
        return True
    else:
        print "Incorrect, correct was:", answer
        return False

# This will run through all the questions
def run_test(questions):
    if len(questions) == 0:
        print "No questions were given."
        # the return exits the function
        return
    index = 0
    right = 0
    while index < len(questions):
        # Check the question
        if check_question(questions[index]):
            right = right + 1
        # go to the next question
        index = index + 1
    # notice the order of the computation, first multiply, then divide
    print "You got", right * 100 / len(questions),\
           "% right out of", len(questions)

# now let's run the questions

run_test(get_questions())
The values True and False point to 1 and 0, respectively. They are often used in sanity checks, loop conditions etc. You will learn more about this a little bit later (chapterBoolean Expressions).
Sample Output:
What color is the daytime sky on a clear day?green
Incorrect, correct was: blue
What is the answer to life, the universe and everything?42
Correct
What is a three letter word for mouse trap?cat
Correct
You got 66 % right out of 3
Exercises
Expand the test.py program so it has a menu giving the option of taking the test, viewing the list of questions and answers, and an option to quit. Also, add a new question to ask, "What noise does a truly advanced machine make?" with the answer of "ping".

Advanced Functions - python (part 7)

Advanced Functions Example 

Some people find this section useful, and some find it confusing. If you find it confusing you can skip it (or just look at the examples.) Now we will do a walk through for the following program:
def mult(a, b):
    if b == 0:
        return 0
    rest = mult(a, b - 1)
    value = a + rest
    return value
print "3 * 2 = ", mult(3, 2)
Output
Basically this program creates a positive integer multiplication function (that is far slower than the built in multiplication function) and then demonstrates this function with a use of the function. This program demonstrates the use of recursion, that is a form of iteration (repetition) in which there is a function that repeatedly calls itself until an exit condition is satisfied. It uses repeated additions to give the same result as mutiplication: e.g. 3 + 3 (addition) gives the same result as 3 * 2 (multiplication).
RUN 1
Question: What is the first thing the program does?
Answer: The first thing done is the function mult is defined with all the lines except the last one.
function mult defined
This creates a function that takes two parameters and returns a value when it is done. Later this function can be run.
What happens next?
The next line after the function, print "3 * 2 = ", mult(3, 2) is run.
And what does this do?
It prints 3 * 2 = and the return value of mult(3, 2)
And what does mult(3, 2) return?
We need to do a walkthrough of the mult function to find out.
RUN 2
What happens next?
The variable a gets the value 3 assigned to it and the variable b gets the value 2 assigned to it.
And then?
The line if b == 0: is run. Since b has the value 2 this is false so the line return 0 is skipped.
And what then?
The line rest = mult(a, b - 1) is run. This line sets the local variable rest to the value of mult(a, b - 1). The value of a is 3 and the value of b is 2 so the function call is mult(3,1)
So what is the value of mult(3, 1) ?
We will need to run the function mult with the parameters 3 and 1.
RUN 2

RUN 3
So what happens next?
The local variables in the new run of the function are set so that a has the value 3 and b has the value 1. Since these are local values these do not affect the previous values of aand b.
And then?
Since b has the value 1 the if statement is false, so the next line becomes rest = mult(a, b - 1).
What does this line do?
This line will assign the value of mult(3, 0) to rest.
So what is that value?
We will have to run the function one more time to find that out. This time a has the value 3 and b has the value 0.
So what happens next?
The first line in the function to run is if b == 0:. b has the value 0 so the next line to run is return 0
And what does the line return 0 do?
This line returns the value 0 out of the function.
So?
So now we know that mult(3, 0) has the value 0. Now we know what the line rest = mult(a, b - 1) did since we have run the function mult with the parameters 3 and 0. We have finished running mult(3, 0) and are now back to running mult(3, 1). The variable rest gets assigned the value 0.
What line is run next?
The line value = a + rest is run next. In this run of the function, a = 3 and rest = 0 so now value = 3.
What happens next?
The line return value is run. This returns 3 from the function. This also exits from the run of the function mult(3, 1). After return is called, we go back to runningmult(3, 2).
Where were we in mult(3, 2)?
We had the variables a = 3 and b = 2 and were examining the line rest = mult(a, b - 1).
So what happens now?
The variable rest get 3 assigned to it. The next line value = a + rest sets value to 3 + 3 or 6.
So now what happens?
The next line runs, this returns 6 from the function. We are now back to running the line print "3 * 2 = ", mult(3, 2) which can now print out the 6.
What is happening overall?
Basically we used two facts to calculate the multiple of the two numbers. The first is that any number times 0 is 0 (x * 0 = 0). The second is that a number times another number is equal to the first number plus the first number times one less than the second number (x * y = x + x * (y - 1)). So what happens is 3 * 2 is first converted into 3 + 3 * 1. Then 3 * 1 is converted into 3 + 3 * 0. Then we know that any number times 0 is 0 so 3 * 0 is 0. Then we can calculate that 3 + 3 * 0 is 3 + 0which is 3. Now we know what 3 * 1 is so we can calculate that 3 + 3 * 1 is 3 + 3 which is 6.
This is how the whole thing works:
3 * 2
3 + 3 * 1
3 + 3 + 3 * 0
3 + 3 + 0
3 + 3
6
Should you still have problems with this example, look at the process backwards. What is the last step that happens? We can easily make out that the result of mult(3, 0) is 0. Since b is 0, the function mult(3, 0) will return 0 and stop.
So what does the previous step do? mult(3, 1) does not return 0 because b is not 0. So the next lines are executed: rest = mult (a, b - 1), which is rest = mult (3, 0), which is 0 as we just worked out. So now the variable rest is set to 0.
The next line adds the value of rest to a, and since a is 3 and rest is 0, the result is 3.
Now we know that the function mult(3, 1) returns 3. But we want to know the result of mult(3,2). Therefore, we need to jump back to the start of the program and execute it one more round: mult(3, 2) sets rest to the result of mult(3, 1). We know from the last round that this result is 3. Then value calculates as a + rest, i. e. 3 + 3. Then the result of 3 * 2 is printed as 6.
The point of this example is that the function mult(a, b) starts itself inside itself. It does this until b reaches 0 and then calculates the result as explained above.
Recursion
Programming constructs of this kind are called recursive and probably the most intuitive definition of recursion is:
Recursion
If you still don't get it, see recursion.
These last two sections were recently written. If you have any comments, found any errors or think I need more/clearer explanations please email. I have been known in the past to make simple things incomprehensible. If the rest of the tutorial has made sense, but this section didn't, it is probably my fault and I would like to know. Thanks.
Examples
factorial.py
#defines a function that calculates the factorial

def factorial(n):
    if n <= 1:
        return 1
    return n * factorial(n - 1)

print "2! =", factorial(2)
print "3! =", factorial(3)
print "4! =", factorial(4)
print "5! =", factorial(5)
Output:
2! = 2
3! = 6
4! = 24
5! = 120
countdown.py
def count_down(n):
    print n
    if n > 0:
        return count_down(n-1)

count_down(5)
Output:
5
4
3
2
1
0
Commented function_interesting.py
# The comments below have been numbered as steps, to make explanation
# of the code easier. Please read according to those steps.
# (step number 1, for example, is at the bottom)


def mult(a, b): # (2.) This function will keep repeating itself, because....
    if b == 0:
        return 0
    rest = mult(a, b - 1) # (3.) ....Once it reaches THIS, the sequence starts over again and goes back to the top!
    value = a + rest
    return value # (4.) therefore, "return value" will not happen until the program gets past step 3 above

print "3 * 2 = ", mult(3, 2) # (1.) The "mult" function will first initiate here


# The "return value" event at the end can therefore only happen
# once b equals zero (b decreases by 1 everytime step 3 happens).
# And only then can the print command at the bottom be displayed.

# See it as kind of a "jump-around" effect. Basically, all you
# should really understand is that the function is reinitiated
# WITHIN ITSELF at step 3. Therefore, the sequence "jumps" back
# to the top.
Commented factorial.py
# Another "jump-around" function example:

def factorial(n): # (2.) So once again, this function will REPEAT itself....
    if n <= 1:
        return 1
    return n * factorial(n - 1) # (3.) Because it RE-initiates HERE, and goes back to the top.

print "2! =", factorial(2) # (1.) The "factorial" function is initiated with this line
print "3! =", factorial(3)
print "4! =", factorial(4)
print "5! =", factorial(5)
Commented countdown.py
# Another "jump-around", nice and easy:


def count_down(n): # (2.) Once again, this sequence will repeat itself....
    print n
    if n > 0:
        return count_down(n-1) # (3.) Because it restarts here, and goes back to the top

count_down(5) # (1.) The "count_down" function initiates here

Functions - python (part 6)

Defining Functions

Creating Functions
To start off this chapter I am going to give you an example of what you could do but shouldn't (so don't type it in):
a = 23
b = -23

if a < 0:
    a = -a
if b < 0:
    b = -b
if a == b:
    print "The absolute values of", a, "and", b, "are equal"
else:
    print "The absolute values of", a, "and", b, "are different"
with the output being:
The absolute values of 23 and 23 are equal
The program seems a little repetitive. Programmers hate to repeat things -- that's what computers are for, after all! (Note also that finding the absolute value changed the value of the variable, which is why it is printing out 23, and not -23 in the output.) Fortunately Python allows you to create functions to remove duplication. Here is the rewritten example:
def absolute_value(n):
    if n < 0:
        n = -n
    return n

a = 23
b = -23

if absolute_value(a) == absolute_value(b):
    print "The absolute values of", a, "and", b, "are equal"
else:
    print "The absolute values of", a, "and", b, "are different"
with the output being:
The absolute values of 23 and -23 are equal
The key feature of this program is the def statement. def (short for define) starts a function definition. def is followed by the name of the function absolute_value. Next comes a '(' followed by the parameter n (n is passed from the program into the function when the function is called). The statements after the ':' are executed when the function is used. The statements continue until either the indented statements end or a return is encountered. The return statement returns a value back to the place where the function was called.
Notice how the values of a and b are not changed. Functions can be used to repeat tasks that don't return values. Here are some examples:
def hello():
    print "Hello"

def area(w, h):
    return w * h

def print_welcome(name):
    print "Welcome", name

hello()
hello()

print_welcome("Fred")
w = 4
h = 5
print "width =", w, "height =", h, "area =", area(w, h)
with output being:
Hello
Hello
Welcome Fred
width = 4 height = 5 area = 20
That example shows some more stuff that you can do with functions. Notice that you can use no arguments or two or more. Notice also when a function doesn't need to send back a value, a return is optional.
Variables in functions
When eliminating repeated code, you often have variables in the repeated code. In Python, these are dealt with in a special way. So far all variables we have seen are global variables. Functions have a special type of variable called local variables. These variables only exist while the function is running. When a local variable has the same name as another variable (such as a global variable), the local variable hides the other. Sound confusing? Well, these next examples (which are a bit contrived) should help clear things up.
a = 4

def print_func():
    a = 17
    print "in  print_func a = ", a

print_func()
print "a = ", a
When run, we will receive an output of:
in print_func a = 17
a = 4
Variable assignments inside a function do not override global variables, they exist only inside the function. Even though a was assigned a new value inside the function, this newly assigned value was only relevant to print_func, when the function finishes running, and the a's values is printed again, we see the originally assigned values.
Complex example
a_var = 10
b_var = 15
e_var = 25

def a_func(a_var):
    print "in a_func a_var = ", a_var
    b_var = 100 + a_var
    d_var = 2 * a_var
    print "in a_func b_var = ", b_var
    print "in a_func d_var = ", d_var
    print "in a_func e_var = ", e_var
    return b_var + 10

c_var = a_func(b_var)

print "a_var = ", a_var
print "b_var = ", b_var
print "c_var = ", c_var
print "d_var = ", d_var
The output is:
in a_func a_var =  15
in a_func b_var =  115
in a_func d_var =  30
in a_func e_var =  25
a_var =  10
b_var =  15
c_var =  125
d_var =

Traceback (most recent call last):
  File "C:\Python24\def2", line 19, in -toplevel-
     print "d_var = ", d_var

NameError: name 'd_var' is not defined
In this example the variables a_var, b_var, and d_var are all local variables when they are inside the function a_func. After the statement return b_var + 10 is run, they all cease to exist. The variable a_var is automatically a local variable since it is a parameter name. The variables b_var and d_var are local variables since they appear on the left of an equals sign in the function in the statements b_var = 100 + a_var and d_var = 2 * a_var .
Inside of the function a_var has no value assigned to it. When the function is called with c_var = a_func(b_var), 15 is assigned to a_var since at that point in time b_varis 15, making the call to the function a_func(15). This ends up setting a_var to 15 when it is inside of a_func.
As you can see, once the function finishes running, the local variables a_var and b_var that had hidden the global variables of the same name are gone. Then the statementprint "a_var = ", a_var prints the value 10 rather than the value 15 since the local variable that hid the global variable is gone.
Another thing to notice is the NameError that happens at the end. This appears since the variable d_var no longer exists since a_func finished. All the local variables are deleted when the function exits. If you want to get something from a function, then you will have to use return something.
One last thing to notice is that the value of e_var remains unchanged inside a_func since it is not a parameter and it never appears on the left of an equals sign inside of the function a_func. When a global variable is accessed inside a function it is the global variable from the outside.
Functions allow local variables that exist only inside the function and can hide other variables that are outside the function.
Examples
temperature2.py
# converts temperature to fahrenheit or celsius

def print_options():
    print "Options:"
    print " 'p' print options"
    print " 'c' convert from celsius"
    print " 'f' convert from fahrenheit"
    print " 'q' quit the program"

def celsius_to_fahrenheit(c_temp):
    return 9.0 / 5.0 * c_temp + 32

def fahrenheit_to_celsius(f_temp):
    return (f_temp - 32.0) * 5.0 / 9.0

choice = "p"
while choice != "q":
    if choice == "c":
        temp = input("Celsius temperature: ")
        print "Fahrenheit:", celsius_to_fahrenheit(temp)
    elif choice == "f":
        temp = input("Fahrenheit temperature: ")
        print "Celsius:", fahrenheit_to_celsius(temp)
    elif choice != "q":
        print_options()
    choice = raw_input("option: ")
Sample Run:
Options:
'p' print options
'c' convert from celsius
'f' convert from fahrenheit
'q' quit the program
option: c
Celsius temperature: 30
Fahrenheit: 86.0
option: f
Fahrenheit temperature: 60
Celsius: 15.5555555556
option: q
area2.py
# By Amos Satterlee
print
def hello():
    print 'Hello!'

def area(width, height):
    return width * height

def print_welcome(name):
    print 'Welcome,', name

name = raw_input('Your Name: ')
hello(),
print_welcome(name)
print
print 'To find the area of a rectangle,'
print 'enter the width and height below.'
print
w = input('Width: ')
while w <= 0:
    print 'Must be a positive number'
    w = input('Width: ')

h = input('Height: ')
while h <= 0:
    print 'Must be a positive number'
    h = input('Height: ')

print 'Width =', w, 'Height =', h, 'so Area =', area(w, h)
Sample Run:
Your Name: Josh
Hello!
Welcome, Josh

To find the area of a rectangle,
enter the width and height below.

Width: -4
Must be a positive number
Width: 4
Height: 3
Width = 4 Height = 3 so Area = 12
Exercises
Rewrite the area2.py program from the Examples above to have a separate function for the area of a square, the area of a rectangle, and the area of a circle (3.14 * radius ** 2). This program should include a menu interface.

Debugging - python (part 5)

Debugging 

What is debugging?
"As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs." — Maurice Wilkes discovers debugging, 1949
By now if you have been messing around with the programs you have probably found that sometimes the program does something you didn't want it to do. This is fairly common. Debugging is the process of figuring out what the computer is doing and then getting it to do what you want it to do. This can be tricky. I once spent nearly a week tracking down and fixing a bug that was caused by someone putting an x where a y should have been.
This chapter will be more abstract than previous chapters.
What should the program do?
The first thing to do (this sounds obvious) is to figure out what the program should be doing if it is running correctly. Come up with some test cases and see what happens. For example, let's say I have a program to compute the perimeter of a rectangle (the sum of the length of all the edges). I have the following test cases:
height width perimeter
3 4 14
2 3 10
4 4 16
2 2 8
5 1 12
I now run my program on all of the test cases and see if the program does what I expect it to do. If it doesn't then I need to find out what the computer is doing.
More commonly some of the test cases will work and some will not. If that is the case you should try and figure out what the working ones have in common. For example here is the output for a perimeter program (you get to see the code in a minute):
Height: 3
Width: 4
perimeter = 15
Height: 2
Width: 3
perimeter = 11
Height: 4
Width: 4
perimeter = 16
Height: 2
Width: 2
perimeter = 8
Height: 5
Width: 1
perimeter = 8
Notice that it didn't work for the first two inputs, it worked for the next two and it didn't work on the last one. Try and figure out what is in common with the working ones. Once you have some idea what the problem is finding the cause is easier. With your own programs you should try more test cases if you need them.
What does the program do?
The next thing to do is to look at the source code. One of the most important things to do while programming is reading source code. The primary way to do this is code walkthroughs.
A code walkthrough starts at the first line, and works its way down until the program is done. While loops and if statements mean that some lines may never be run and some lines are run many times. At each line you figure out what Python has done.
Lets start with the simple perimeter program. Don't type it in, you are going to read it, not run it. The source code is:
height = input("Height: ")
width = input("Width: ")
print "perimeter =", width + height + width + width
Question: What is the first line Python runs?
Answer: The first line is always run first. In this case it is: height = input("Height: ")
What does that line do?
Prints Height: , waits for the user to type a number in, and puts that in the variable height.
What is the next line that runs?
In general, it is the next line down which is: width = input("Width: ")
What does that line do?
Prints Width: , waits for the user to type a number in, and puts what the user types in the variable width.
What is the next line that runs?
When the next line is not indented more or less than the current line, it is the line right afterwards, so it is: print "perimeter = ", width + height + width + width (It may also run a function in the current line, but that's a future chapter.) What does that line do?
First it prints perimeter = , then it prints width + height + width + width.
Does width + height + width + width calculate the perimeter properly?
Let's see, perimeter of a rectangle is the bottom (width) plus the left side (height) plus the top (width) plus the right side (huh?). The last item should be the right side's length, or the height.
Do you understand why some of the times the perimeter was calculated "correctly"?  
It was calculated correctly when the width and the height were equal.
The next program we will do a code walkthrough for is a program that is supposed to print out 5 dots on the screen. However, this is what the program is outputting:
. . . .
And here is the program:
number = 5
while number > 1:
    print ".",
    number = number - 1
print
This program will be more complex to walkthrough since it now has indented portions (or control structures). Let us begin.
What is the first line to be run?
The first line of the file: number = 5
What does it do?
Puts the number 5 in the variable number.
What is the next line?
The next line is: while number > 1:
What does it do?
Well, while statements in general look at their expression, and if it is true they do the next indented block of code, otherwise they skip the next indented block of code.
So what does it do right now?
If number > 1 is true then the next two lines will be run.
So is number > 1?
The last value put into number was 5 and 5 > 1 so yes.
So what is the next line?
Since the while was true the next line is: print ".",
What does that line do?
Prints one dot and since the statement ends with a ',' the next print statement will not be on a different screen line.
What is the next line?
number = number - 1 since that is following line and there are no indent changes.
What does it do?
It calculates number - 1, which is the current value of number (or 5) subtracts 1 from it, and makes that the new value of number. So basically it changes number's value from 5 to 4.
What is the next line?
Well, the indent level decreases so we have to look at what type of control structure it is. It is a while loop, so we have to go back to the while clause which is while number > 1:
What does it do?
It looks at the value of number, which is 4, and compares it to 1 and since 4 > 1 the while loop continues.
What is the next line?
Since the while loop was true, the next line is: print ".",
What does it do?
It prints a second dot on the line.
What is the next line?
No indent change so it is: number = number - 1
And what does it do?
It takes the current value of number (4), subtracts 1 from it, which gives it 3 and then finally makes 3 the new value of number.
What is the next line?
Since there is an indent change caused by the end of the while loop, the next line is: while number > 1:
What does it do?
It compares the current value of number (3) to 1. 3 > 1 so the while loop continues.
What is the next line?
Since the while loop condition was true the next line is: print ".",
And it does what?
A third dot is printed on the line.
What is the next line?
It is: number = number - 1
What does it do?
It takes the current value of number (3) subtracts from it 1 and makes the 2 the new value of number.
What is the next line?
Back up to the start of the while loop: while number > 1:
What does it do?
It compares the current value of number (2) to 1. Since 2 > 1 the while loop continues.
What is the next line?
Since the while loop is continuing: print ".",
What does it do?
It discovers the meaning of life, the universe and everything. I'm joking. (I had to make sure you were awake.) The line prints a fourth dot on the screen.
What is the next line?
It's: number = number - 1
What does it do?
Takes the current value of number (2) subtracts 1 and makes 1 the new value of number.
What is the next line?
Back up to the while loop: while number > 1:
What does the line do?
It compares the current value of number (1) to 1. Since 1 > 1 is false (one is not greater than one), the while loop exits.
What is the next line?
Since the while loop condition was false the next line is the line after the while loop exits, or: print
What does that line do?
Makes the screen go to the next line.
Why doesn't the program print 5 dots?
The loop exits 1 dot too soon.
How can we fix that?
Make the loop exit 1 dot later.
And how do we do that?
There are several ways. One way would be to change the while loop to: while number > 0: Another way would be to change the conditional to: number >= 1 There are a couple others.
How do I fix the program?
You need to figure out what the program is doing. You need to figure out what the program should do. Figure out what the difference between the two is. Debugging is a skill that has to be practiced to be learned. If you can't figure it out after an hour, take a break, talk to someone about the problem or contemplate the lint in your navel. Come back in a while and you will probably have new ideas about the problem. Good luck.

If statement - python (part 4)

Decisions

If statement
As always I believe I should start each chapter with a warm-up typing exercise, so here is a short program to compute the absolute value of a number:
n = input("Number? ")
if n < 0:
   print "The absolute value of", n, "is", -n
else:
   print "The absolute value of", n, "is", n
Here is the output from the two times that I ran this program:
Number? -34
The absolute value of -34 is 34
Number? 1
The absolute value of 1 is 1
So what does the computer do when it sees this piece of code? First it prompts the user for a number with the statement "n = input("Number? ")". Next it reads the line "if n < 0:". If n is less than zero Python runs the line "print "The absolute value of", n, "is", -n". Otherwise it runs the line "print "The absolute value of", n, "is", n".
More formally Python looks at whether the expression n < 0 is true or false. An if statement is followed by an indented block of statements that are run when the expression is true. Optionally after the if statement is an else statement and another indented block of statements. This second block of statements is run if the expression is false.
There are a number of different tests that an expression can have. Here is a table of all of them:
operator function
< less than
<= less than or equal to
> greater than
>= greater than or equal to
== equal
!= not equal
<> another way to say not equal (old style, not recommended)
Another feature of the if command is the elif statement. It stands for else if and means if the original if statement is false but the elif part is true, then do the elif part. And if neither the if or elif expressions are true, then do what's in the else block. Here's an example:
a = 0
while a < 10:
    a = a + 1
    if a > 5:
        print a, ">", 5
    elif a <= 7:
        print a, "<=", 7
    else:
        print "Neither test was true"
and the output:
1 <= 7
2 <= 7
3 <= 7
4 <= 7
5 <= 7
6 > 5
7 > 5
8 > 5
9 > 5
10 > 5
Notice how the elif a <= 7 is only tested when the if statement fails to be true. There can be more than one elif expression, allowing multiple tests to be done in a singleif statement.
Examples
# This Program Demonstrates the use of the == operator
# using numbers
print 5 == 6
# Using variables
x = 5
y = 8
print x == y
And the output
False
False
High_low.py
# Plays the guessing game higher or lower

# This should actually be something that is semi random like the
# last digits of the time or something else, but that will have to
# wait till a later chapter.  (Extra Credit, modify it to be random
# after the Modules chapter)
number = 78
guess = 0

while guess != number:
    guess = input("Guess a number: ")
    if guess > number:
        print "Too high"
    elif guess < number:
        print "Too low"

print "Just right"
Sample run:
Guess a number: 100
Too high
Guess a number: 50
Too low
Guess a number: 75
Too low
Guess a number: 87
Too high
Guess a number: 81
Too high
Guess a number: 78
Just right
even.py
# Asks for a number.
# Prints if it is even or odd

number = input("Tell me a number: ")
if number % 2 == 0:
    print number, "is even."
elif number % 2 == 1:
    print number, "is odd."
else:
    print number, "is very strange."
Sample runs:
Tell me a number: 3
3 is odd.
Tell me a number: 2
2 is even.
Tell me a number: 3.14159
3.14159 is very strange.
average1.py
# keeps asking for numbers until 0 is entered.
# Prints the average value.

count = 0
sum = 0.0
number = 1 # set to something that will not exit the while loop immediately.

print "Enter 0 to exit the loop"

while number != 0:
    number = input("Enter a number: ")
    if number != 0:
        count = count + 1
        sum = sum + number

print "The average was:", sum / count
Sample runs:
Enter 0 to exit the loop
Enter a number: 3
Enter a number: 5
Enter a number: 0
The average was: 4.0
Enter 0 to exit the loop
Enter a number: 1
Enter a number: 4
Enter a number: 3
Enter a number: 0
The average was: 2.66666666667
average2.py
# keeps asking for numbers until count numbers have been entered.
# Prints the average value.

sum = 0.0

print "This program will take several numbers then average them"
count = input("How many numbers would you like to average: ")
current_count = 0

while current_count < count:
    current_count = current_count + 1
    print "Number", current_count
    number = input("Enter a number: ")
    sum = sum + number

print "The average was:", sum / count
Sample runs:
This program will take several numbers then average them
How many numbers would you like to average: 2
Number 1
Enter a number: 3
Number 2
Enter a number: 5
The average was: 4.0
This program will take several numbers then average them
How many numbers would you like to average: 3
Number 1
Enter a number: 1
Number 2
Enter a number: 4
Number 3
Enter a number: 3
The average was: 2.66666666667
Exercises
Modify the higher or lower program from this section to keep track of how many times the user has entered the wrong number. If it is more than 3 times, print "That must have been complicated." Note that the program does not have to quit asking for the number before it is guessed, it just has to print this after the number is guessed.
Write a program that asks for two numbers. If the sum of the numbers is greater than 100, print "That is a big number."
Write a program that asks the user their name, if they enter your name say "That is a nice name", if they enter "John Cleese" or "Michael Palin", tell them how you feel about them ;), otherwise tell them "You have a nice name."