Most of this is covered late in Chapter 2 of *Practical Programming* and
Chapter 3 of *Think Python*. Chapter 6 of *Think Python* goes into more
detail, but we are not quite ready for that yet.

Recall our program to compute the surface area and volume of a cylinder:

>>> pi = 3.14159 >>> radius = 2 >>> height = 10 >>> base_area = pi * radius ** 2 >>> volume = base_area * height >>> surface_area = 2 * base_area + 2 * pi * radius * height >>> print "volume is", volume, ", surface area is", surface_area volume is 125.6636 , surface area is 150.79632

If we want to run all or part of this again, on different values, we either have to edit the program and rerun it, or we have to type the statements all over again.

Instead, we will gather the code into one or more Python functions that we can run repeatedly.

The purpose of today’s class is to introduce the basics of writing and running Python functions.

In mathematics, you might write a function to calculate the area of a circle as

In Python, when typing directly into the interpreter, we write

>>> def area_circle(radius): ... pi = 3.14159 ... return pi * radius ** 2

Then we can run this using

>>> area_circle(1) >>> area_circle(2) >>> area_circle(75.1)

Note that by using examples with small values for the radius we can easily check that our function is correct.

Important syntax includes

- Use of the keyword
`def`and the`:`to indicate the start of the function - Indentation for the lines after the
`def`line - Blank line at the end of the function

The

`...`are produced by the Python interpreter, just like the`>>>`are.- Use of the keyword

Reads the keyword

`def`and notes that a function is being defined.- The line that starts with
`def`is called the function*header*

- The line that starts with
Reads the rest of the function definition, checking its syntax

Notes the end of the definition when the blank line is reached.

Sees the function call

>>> area_circle(1)

at what’s known as the “top level” or “main level” of execution (indicated by the presence of

`>>>`), and- Jumps back up to the function
- Assigns 1 to
`radius` - Runs the code inside the function
- Returns the result of the calculation back to the top level and outputs the returned result

Repeats the process of running the function at the line

>>> area_circle(2)

this time with

`radius`assigned the value 2Repeats the process again at the line

>>> area_circle(75.1)

To re-iterate, the “flow of control” of Python here involves

- Reading the function definition without executing
- Seeing a “call” to the function, jumping up to the start of the function and executing
- Returning back to the place in the program that called the function and continuing.

*Arguments*are the values 1, 2 and 75.1 in our above examples.- These are each passed to the
*parameter*called`radius`named in the function header. This parameter is used just like a variable in the function. - The variable
`pi`is a*local variable*to the function. - Neither
`pi`nor`radius`exists at the top / main level. At this level, they are “undefined variables”. Try it out.

- Instead of typing directly into the interpreter, we can type the
function into a file, save the file, and then run it.
- This is what happens when you type into the upper pane of the Wing IDE display.

- We run the program by clicking on the green triangle. The results appear in the “Python Shell” on the lower right.
- The flow of control is the same as if we typed directly into the
interpreter, but...
- We need
`print`statements to generate the output - We do not need the blank line to end the function definition. We just need to stop the indentation.

- We need
- We will do this in class.

For the following problems, write your code as though it is being typed into a file (or, if you have your laptop, type it into a file in the upper left corner of the Wing IDE).

- Write a function to convert the Celsius temperature to a Fahrenheit temperature and return it.
- Write code to use the function.
- What are the arguments, parameters and local variables?
- Write a second function to convert a Fahrenheit temperature to Celsius and return it.
- How might you use the two functions together to test that they are both correct?

For our volume calculation, we write a function involving two parameters, called with two arguments:

def volume(radius, height): pi = 3.14159 return pi * radius ** 2 * height print "volume of cylinder with radius", 1, "and height 2 is", volume(1,2) print "volume of cylinder with radius", 2, "and height 1 is", volume(2,1)

Python determines which argument goes to which parameter based on the order of the arguments, the first going to

`radius`and the second going to`height`.In this example, we have provided clearer, more extensive output.

- The text between the
`"`symbols is output as is. More on this in Lecture 4.

- The text between the

Some Python functions do not return a value — usually they print out their result.

For example,

def volumep(r, h): pi = 3.14159 vol = pi * r ** 2 * h print "The volume of a cylinder with radius", r, "and height", h, "is", vol volumep(1,2) volumep(2,1)

The end of the function is indicated by the line starting at

`volumep(1,2)`, which is at the**same level of indentation**as the`def`.There is no

`return`and the calling code does not attempt to use (e.g. print) a returned value.- We could add a
`return`with no value at the end of the function.

- We could add a
The choice between using functions that do and do not have return values will become clear over time.

- Write a Python function that calculates and returns the average of three numbers. Add code to show how this is called.
- Write a Python function that calculates and outputs the average of three numbers, without returning the result. Show how this is called.

Let’s make use of our area of circle function to compute the surface area of the cylinder.

Here is the Python code, in file

`surface_area.py`:def area_cylinder(radius,height): circle_area = area_circle(radius) pi = 3.14159 height_area = 2 * radius * pi * height return 2*circle_area + height_area def area_circle(radius): pi = 3.14159 return pi * radius ** 2 print 'The area of a circle of radius 1 is', area_circle(1) r = 2 height = 10 print 'The surface area of a cylinder with radius', r print 'and height', height, 'is', area_cylinder(r,height)

Now we’ve defined two functions, one of which calls the other.

Flow of control proceeds in two different ways here:

- Starting at the first
`print`at the top level, into`area_circle`and back. - At the second
`print`- into
`area_cylinder`, - into
`area_circle`, - back to
`area_cylinder`, and - back to the top level.

- into

- Starting at the first
The Python interpreter keeps track of where it is working and where to return when it is done with a function, even if it is back into another function.

We can gather our code in one complete set of functions, writing them into a file called

`area_volume.py`:def area_circle(radius): pi = 3.14159 return pi * radius ** 2 def volume_cylinder(radius,height): area = area_circle(radius) return area * height def area_cylinder(radius,height): circle_area = area_circle(radius) pi = 3.14159 height_area = 2 * radius * pi * height return 2*circle_area + height_area def area_and_volume(radius, height): print "For a cylinder with radius", radius, "and height", height print "The surface area is", area_cylinder(radius,height) print "The volume is", volume_cylinder(radius,height)

Now we have functionality that we can use to generate clear, complete output for many different values of the radius of a circle and the base radius and height of a cylinder.

Why is it NOT a mistake to use the same name, for example `radius`, in
different functions (and sometimes at the top level)?

In order to check our understanding, we will play around with the code and make some mistakes on purpose

- Removing
`pi` - Changing the name of a function
- Switching the order of the parameters in a function call
- Making an error in our calculation

- Write a function to compute the area of a rectangle.
- Write a second function that takes the length, width and height of a rectangular solid and computes its surface area. It should use the function you wrote to compute the area of the rectangle, calling it three times.

We write code that is

- Easier to think about and write
- Easier to test: we can check the correctness of
`area_circle`before we test`area_cylinder`. - Clearer for someone else to read
- Reusable in other programs

Together these define the notion of *encapsulation*, another important
idea in computer science!

- Functions for encapsulation and reuse
- Function syntax
- Arguments, parameters and local variables
- Flow of control, including functions that call other functions
- Built-in functions
- You can find the code developed in this class under the class
modules. In particular,
`area_solid`and`area_volume`.

Concepts to review before next class:

Expressions:What type of data do they return?Try typing simple math formula to the Python interpreter:

>>> 1 + 2 * 3 / 3 * 4**2 **3 - 3 / 3*4and manually find the output. Don’t be fooled by the spaces! Operator precedence is in effect. Try writing your own expressions.

Variables:Do you know what are valid and invalid variable names?What is the difference in the output between:

>>> 3 + 4 >>> print 3 + 4 >>> x = 3 + 4 >>> print x >>> print x = 3+4Try to guess before typing it in, but make a habit of typing simple statements like this and looking at the result.

Assignment:Can you trace the value of a variable after many different assignments? Don’t be fooled by the name of variables. Try to do it manually:>>> one = 2 >>> two = 1 >>> three = 4 >>> one += 3 * two >>> two -= 3 * one + threeBy the way, make a habit of picking nice variable names. Otherwise, I will torture you with questions like this. Your variables should be meaningful whenever possible both to you and to anyone else reading your code.

Functions:Write the functions from class on your own using the Python interpreter. Try to do it without looking at notes. Can you do it?

- Write a function that returns a value.
- Write a function with no return.
- Write a function where
returnis not the last statement in the function.- Call these functions by either printing their result or assigning their results to a value. Here, I’ll get you started.
def regenerate_doctor(doctor_number): return doctor_number+1 def regenerate_tardis(doctor_number): print "Tardis is now ready for doctor number", doctor_number def eliminate_doctor(doctor_number): return 0 print "You will be eliminated doctor", doctor_number

- Write functions that use the built-in functions. Make sure you memorize what they are and how they are used.

- Finally, write some functions to a file and execute them from within the file. Now, execute the file. Make sure all of this is quite easy to do without consulting the course notes by monday.