# Functions and Modules¶

See also

Text, Chapter 8

Read time: 25 minutes (6371 words)

We introduced Functions earlier in the course, since the concept of packaging a
block of code we can use over and over is critical to programming. In this
section, we will complete our discussion on functions and show how to package
them into a useful form we really can use in other programs. The form is called
a `module`

.

## Reviewing the function¶

As you recall, a function is a block of code that we give a name. That block
can have `parameters`

, which provide data for the function to work with, and it
can `return`

a value to whatever code `called`

it. Both `parameters`

and
`return values`

are optional.

Here is a simple function, demonstrating all the parts:

```
def adder(val1, val2):
sum = val1 + val2
return sum
```

We can `call`

this function from any chunk of code that can `see`

the
definition. You should review the lecture on `scope`

to make sure you can
identify where the function can be called.

Here is some code that will work:

```
print("The sum of 5 and 7 is",adder(5,7))
```

In this statement, we are calling another function, `print`

, which is being
handed two `parameters`

. The first is a string, and the second is a call to
our `adder`

function. Python will halt processing or the `print`

function,
and call the `adder`

function. When that function returns, Python will hand
that value to the `print`

function so it can display the results.

Here is what we see if we test this in the Python interpreter:

```
>>> def adder(val1, val2):
... sum = val1 + val2
... return sum
...
>>> print("The sum of 5 and 7 is",adder(5,7))
The sum of 5 and 7 is 12
```

Looks like it worked!

Note

Do any of you see something interesting about how `print`

works? It seems
that it can take a different number of parameters, depending on what we
want to print. We will see how to do this later.

What would happen if we ran this code:

```
adder(7,9)
```

Actually, Python would call the function and get the result back. However, since we are not doing anything with the returned value, it is just discarded!

## Returning multiple values¶

In some cases, you might want to create a function that returns more than one value. Python supports this as long as you do things properly. Here is a (way too) simple example:

```
def funny():
return 5,7
a,b = funny()
print(a,b)
```

Running this gives:

```
>>> def funny():
... return 5,7
...
>>> a,b = funny()
>>> print(a,b)
5 7
```

How about this:

```
>>> print("The sum of 5 and 7 is",adder(funny()))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: adder() takes exactly 2 arguments (1 given)
```

Phooey! That did not work, but this does:

```
>>> a,b = funny()
>>> print("The sum of 5 and 7 is",adder(a,b))
The sum of 5 and 7 is 12
```

The `funny`

function is returning multiple values, so we need to identify
multiple places to put the results. Later we will see that Python supports a
special kind of data container that can hold a bunch of values. It is called a
`list`

, but we are not ready for that yet.

## Creating a module¶

A module is a file containing variables and functions we can use in other parts
of a Python program. We have been using modules whenever we `import`

something into our program, like when we used the `sqrt`

function contained
in the standard Python `math`

module. What we want to do now is to figure out
how to build our own module. We will do this by writing a super simple version
of `math`

called `mymath`

. This module will do only two things, define a
value for `PI`

and figure out the trigonometric `sine`

of an angle
expressed in degrees. (The real `math`

module wants angles in something
called `radians`

which are hard for people to figure out until you take a
trig class! (Or work this week’s lab assignment!)

Start off by building a directory to hold the test code we will produce in this lecture:

```
C:\COSC1336> mkdir modules
C:\COSC1336> cd modules
C:\COSC1336\modules>
```

To build our module, we start off by creating a new file, `mymath.py`

, that
looks like this:

```
# mymath - a simple trig module
PI = 3.1415926
def sin(angle):
return 0
if __name__ == '__main__':
print("Testing the mymath module")
print("The sin of 30 should be 0.5, and we get")
print(sin(30))
print("If this is not right, we have more work to do on this module!")
```

Note

That last chunk of code is a common pattern in Python modules. If we
`import`

`mymath`

into another program, Python will ignore the code at
the end and you will see no output from that code. If, however, you ask
Python to process the module file directly (using `python mymath.py`

),
then Python will process the code t the bottom and you will see the test
output you placed there. This is handy when developing the module.

Let’s test our new module by asking Python to run the module file:

```
python3 mymath.py
Testing the mymath module
The sin of 45 should be 0.5, and we get
0
If this is not right, we have more work to do on this module!
```

It looks like we have more work to do.

### Setting up a better test¶

Since we are trying to build a function that works something like the real
`math`

module, let’s use that real module to test our new one. Sounds silly,
but it will work:

```
# mymath - a simple trig module
import math
PI = 3.1415926
def sin(angle):
return 0
if __name__ == '__main__':
angle = 30.0
radians = math.pi * angle/180.0
print("Testing the mymath module")
print("The sin of",angle, "should be",math.sin(radians), "and we get")
print(sin(angle))
print("If this is not right, we have more work to do on this module!")
```

Look closely at how this code is set up. We have not really changed the module code, but we have changed the test code at the bottom. Testing the module will help us know when we have our module code written correctly (at least for one case). We will do a better job of testing later.

### Referencing module names¶

Do you see how we referenced named from the real `math`

module? In this
example, we only `imported`

the name of the module. In order to access the
names in that module, we use `modulename.name`

notation. In the `math`

module we can access a better value for `PI`

by using `math.pi`

and get the
real `sin`

function using `math.sin`

. Remember how we used the `sqrt`

function in the `math`

module earlier:

```
from math import sqrt
x = sqrt(5)
```

In this code, we used a different form of `import`

. This form specifically
makes a single name(in this example) available without needing to add the
module name to the front. You choose which approach you like better.

There is another form we can use:

```
from math import *
x = sqrt(5)
```

In this form, we ask Python to make all names defined in the module available
to the program file with this `import`

line.

Note

If you want to see all the names a module has in it, you can do this from the Python interpreter:

```
```

```
>>> import math
>>> dir(math)
['__doc__', '__file__', '__name__', '__package__', 'acos', 'acosh', 'asin', 'asinh',
'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf',
'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum',
'gamma', 'hypot', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10',
'log1p', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
```

Boy, that is a lot of math stuff!

## How does Python find modules¶

For our experiments, Python is finding our `mymath`

module by looking in the
current directory (where you are working) for the file `mymath.py`

. If it
fails to find it, it also looks in standard places in the Python distribution
on your systems. We will see how this is done a bit later in the course. The
`math`

module is a bit different, since Python, itself, is written in C++,
and most of the math routines are part of that language. Other standard modules
that come with Python are found in lives in `c:\Python33\Lib`

. There are
good references to the tools found there. My favorite is Doug Hellmann’s
`Python Module of the Week`

found at http://www.doughellmann.com/PyMOTW.

We will learn a bit more about modules are we work through the rest of the course!

## Using your module¶

We have enough code in `mymath.py`

to show how to use it. Let’s create a test
program in `test.py`

:

```
# test.py - a program that uses our mymath module
import mymath
def main():
print("Testing mymath")
sinx = mymath.sin(30.0)
print("The sin of 30 degrees is", sinx)
main()
```

In this version, we did not import the names, so we need to use the module.function form to call the new function. We could have done this instead:

```
# test.py - a program that uses our mymath module
from mymath import sin
def main():
print("Testing mymath")
sinx = sin(30.0)
print("The sin of 30 degrees is", sinx)
main()
```

We need to be careful if we try to import two modules that provide the same
functions. If we imported the tried to import the `sin`

function from both
`math`

and `mymath`

Python would not be able to figure out which is which:

The solution is to use the module.name approach for one or both. This would work:

```
# test.py - a program that uses our mymath module
import mymath
from math import sin
def main():
print("Testing mymath")
sinx = mymath.sin(30.0)
print("The sin of 30 degrees is", sinx)
print("Python says the sin of 30 degrees is", math.sin(30*math.pi/180.0))
main()
```

In that last line I an converting degrees into radians (we will look at that in
this week’s lab) before handing the result to the `math`

`sin`

function.

Phew!