# How to Program, Part IV

Sometimes we may want to take a calculation and re-use it several times in a program. We do this by making a function.

You can think of a function as something that goes to its "In" box for work, does something with what it finds there, and produces something else and puts it in the "Out" box.

Here we show you some examples of really simple functions:

 simplef.py 1 def timestwo(x): 2 return 2*x 3 4 def plusthree(x): 5 return x+3 6 7 def square(x): 8 return x*x 9 10 print square(plusthree(timestwo(3))) \$ python ./simplef.py 81

Here is a more complex example based on our grocery shopping task:

 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 function and returns the computed value.

Variables defined inside a function are not visible outside.

 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 variables defined outside the function are visible inside.

 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.

 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

If a function doesn't have a return statement, it returns "None."

 none.py 1 def rnone(): 2 pass 3 4 print rnone() \$ python ./none.py None

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."

 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:

 basictypes.py 1 print 1/2 2 print 1.0/2 3 print 1/2.0 4 print 1.0/2.0 \$ python ./basictypes.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.

 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.

 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.

 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.

 rand.py 1 import random 2 3 print random.random() \$ python ./rand.py 0.261743293979

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

 dice.py 1 import random 2 3 for i in range(4): 4 print 'roll =',random.randint(1,6) \$ python ./dice.py roll = 6 roll = 1 roll = 2 roll = 1

This prints a random number between 1 and 6. Try it!

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

 url.py 1 import urllib 2 3 url = urllib.urlopen("http://scifi.com") 4 text = url.readline() 5 print text \$ python ./url.py

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:

 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 the output (line 2), and the input (line 4).

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

 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.

 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]

Problems:

1. What does the function "ad" do?
 what4a.py 1 def ad(a,b): 2 return a+b 3 4 v1 = ad(3,7) 5 v2 = ad(9,2) 6 print v1,v2 \$ python ./what4a.py 10 11
2. Why doesn't this program print anything?
 what4b.py 1 def pr(): 2 print "Hello" 3 4 pr \$ python ./what4b.py
3. Why does this function print "None" and not 7?
 why40.py 1 def ad(a,b): 2 s = a+b 3 4 v1 = ad(3,4) 5 print v1 \$ python ./why40.py None
4. What does the function "sm" do?
 what40.py 1 def sm(a): 2 s = 0 3 for v in a: 4 s += v 5 return s 6 7 print sm([1,3,5]) 8 ar = [2,4,6] 9 print sm(ar) \$ python ./what40.py 9 12
5. What does the function "ra" do?
 what41.py 1 import random 2 def ra(n): 3 a = [] 4 for i in range(n): 5 a += [random.randint(1,100)] 6 return a; 7 8 print ra(3) 9 ar = ra(5) 10 print ar \$ python ./what41.py [10, 56, 52] [17, 20, 73, 73, 26]
6. What does the function "mn" do?
 what42.py 1 import random 2 def mn(a): 3 r = a[0] 4 for i in range(1,len(a)): 5 if a[i] < r: 6 r = a[i] 7 return r 8 9 ar = [] 10 for i in range(3): 11 ar.append(random.randint(1,100)) 12 print mn(ar),ar \$ python ./what42.py 35 [35, 36, 68]
7. This program is supposed to print ['h', 'e', 'l', 'l', 'o']. What's wrong with it? How do we fix it?
 wrong43.py 1 li = [] 2 for c in "hello": 3 li = li.append(c) 4 print li \$ python ./wrong43.py Traceback (most recent call last):   File "./wrong43.py", line 3, in      li = li.append(c) AttributeError: 'NoneType' object has no attribute 'append'
8. Write a function that takes an argument called name and prints out a greeting to that name, i.e. greet("Bob") produces the output: "Hello, Bob".
9. Write a program that takes two numbers a, and b and returns the smaller number first and the larger number second, i.e minmax(3,4) produces 3,4 and minmax(6,5) produces 5,6.
 prev next