1. How to Program, Part I
  2. How to Program, Part II
  3. How to Program, Part III
  4. How to Program, Part IV
  5. How to Program, Part V
  6. exercises
  7. pyMPI tutorial
  8. Calculating PI, Part I
  9. Calculating PI, Part II
  10. Calculating PI, Part III
  11. Poogle - Web Search
  12. Mandelbrot Sets
  13. Mandelbrot, The Code
  14. Mandelbrot, The Images
  15. Conway's Life, Part I
  16. Life Code Listing
  17. Conway's Life, Part II
  18. MPI Life Code Listing

How to Program, Part IV

Sometimes we may want to take a calculation and re-use it several times in a program.

file: shop.py
1 def ring_up(total,name,price):
2     tax_rate = 6
3     tax = price * tax_rate / 100
4     print name,price,tax
5     return total+price+tax
6 
7 total = 0
8 total = ring_up(total,"milk",3.89)
9 total = ring_up(total,"cookies",1.55)
10 total = ring_up(total,"apples",4.99)
> python shop.py
milk 3.89 0.2334
cookies 1.55 0.093
apples 4.99 0.2994

In this case, by defining the function named "ring_up" we've saved ourselves some coding. We can use ring_up() to compute the total of our purchases, along with taxes, as well as an itemized list. Each call to "ring_up" executes the four lines of code present in its definition.

Notice the syntax: the values "total", "name", and "price" are passed to the function named ring_up. These variables are called "arguments." The "return" line causes an exit from the funtion and returns the computed value.

Variables defined inside a function are not visible outside.

file: nshop.py
1 def ring_up(total,name,price):
2     tax_rate = 6
3     tax = price * tax_rate / 100
4     print name,price,tax
5     return total+price+tax
6 
7 total = 0
8 total = ring_up(total,"milk",3.89)
9 print tax_rate
> python nshop.py
milk 3.89 0.2334
Traceback (most recent call last):
  File "nshop.py", line 9, in ?
    print tax_rate
NameError: name 'tax_rate' is not defined

But ariables defined outside the function are visible inside.

file: nshop2.py
1 tax_rate = 6
2 def ring_up(total,name,price):
3     tax = price * tax_rate / 100
4     print name,price,tax
5     return total+price+tax
6 
7 total = 0
8 total = ring_up(total,"milk",3.89)
9 print tax_rate
> python nshop2.py
milk 3.89 0.2334
6

It is as if the variables inside a function live in their own private world.

Functions can have multiple return points.

file: multi.py
1 def multi(x):
2     if x < 3:
3         return x - 100
4     else:
5         return 2*x
6 
7 print multi(2),multi(4)
> python multi.py
-98 8

In our next program, we want to make use of a function we defined in the "shop.py" program above. We can do this using an "import."

file: ring.py
1 import shop
2 
3 total = 0
4 total = shop.ring_up(total,"fudge",3.25)
5 total = shop.ring_up(total,"bag of lemons",1.25)
6 total = shop.ring_up(total,"instant tea",1.89)
7 print "total =",total
> python ring.py
milk 3.89 0.2334
cookies 1.55 0.093
apples 4.99 0.2994
fudge 3.25 0.195
bag of lemons 1.25 0.075
instant tea 1.89 0.1134
total = 6.7734

Notice what happened. "import shop.py" read the contents of "shop.py" and then made the function "ring_up()" available to us in our ring.py program. However, in order to use it, we have to use the prefix "shop." in front of each call to "ring_up()".

One subtle point here that you should be aware of. Integers and floating point numbers are different:

file: types.py
1 print 1/2
2 print 1.0/2
3 print 1/2.0
4 print 1.0/2.0
> python types.py
0
0.5
0.5
0.5

When integers are used, no decimal values are ever calculated. If you want to see decimal points in the result, you have to use them in one of the values involved in the computation. Thus, the tax calculation we did in "shop.py" would fail if we used an integer for the price.

file: shop_ohno.py
1 import shop
2 
3 total = 0
4 total = shop.ring_up(total,"ding dongs",3)
5 print "total =",total # oh no! tax calculation failed!
> python shop_ohno.py
milk 3.89 0.2334
cookies 1.55 0.093
apples 4.99 0.2994
ding dongs 3 0
total = 3

There are lots of standard functions that you can import.

file: math1.py
1 import math
2 
3 print math.sqrt(4)
> python math1.py
2.0

The above program will just print "2" (the function math.sqrt() is the square root function), as you'd expect.

file: math2.py
1 import math
2 
3 print math.sin(math.pi/4)
> python math2.py
0.707106781187

Here we see that it is possible to import variables (in this case "math.pi") as well as functions.

file: rand.py
1 import random
2 
3 print random.random()
> python rand.py
0.908264820247

This prints a random number between 0.0 and 1.0. Try it!

This next program can be used to fetch the contents of a web page:

file: url.py
1 import urllib
2 
3 url = urllib.urlopen("http://scifi.com")
4 text = url.readline() 
5 print text
> python url.py
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

This probably looks a bit strange to you. Some variables have methods attached to them. In this case, the variable url has a method attached to it called readline. I don't want to dwell on this too deeply, it's just a hint of things to come. We have, however, already seen this kind of thing in lesson 3. Variables of type list have an "append" method inside them.

One last point...

You can return more than one value from a function using something called "tuples." We aren't going to go into too much detail about them here, just to show you this quick example:

file: tuple.py
1 def div(d1,d2):
2     return (d1+d2,d1-d2)
3 
4 (a,b)=div(4,2)
5 print a,b
> python tuple.py
6 2

The idea is that you can group a set of values together in both return statement (line 2), and when the function is called (line 4).

Actually, this also works without the parenthesis, but using them might make it easier for you to read the code.

file: tuple2.py
1 def div(d1,d2):
2     return d1+d2,d1-d2
3 
4 a,b=div(4,2)
5 print a,b
> python tuple2.py
6 2

Here is an example that combines what we know about arrays and functions.in it we will build a new array, one in which the order of elements is reversed relative to the original one.

file: reverse.py
1 def rev(a):
2     b = []
3     n = len(a)
4     for i in range(n):
5         b.append(a[n-i-1])
6     return b
7 x = [1,2,3,8,20]
8 y = rev(x)
9 print x,y
> python reverse.py
[1, 2, 3, 8, 20] [20, 8, 3, 2, 1]