Lecture 5 — Python Functions
===============================
Reading
-------
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.
Why Functions?
---------------
- The purpose of today’s class is to introduce the basics of writing
and running Python functions.
- Recall Lab 1 for computing disk size. We had to repeat the same
computation three times for different input.
- It is easy to find a
mistake and forget to fix it in all copies of the same code.
- It is also hard to distinguish between the same code
repeated three times and three different computations.
- Programmer's motto: DRY -- don't repeat yourself.
- Define it once and use it multiple times.
- Functions are extremely useful for writing complex programs:
- They divide complex operations into a combination of simpler steps.
- They make programs easier to read and debug by abstracting out frequently
repeated code.
Functions
----------
- Often a function is a piece of program that computes one specific
thing.
- It should be possible to infer what the function does from the
function name. Think of the names of functions in the math module:
``math.sqrt``, ``math.truncate``, ...
- The function
- Takes as input one or more arguments.
- Computes a new value, a string or a number.
- Returns the value, so that it can be assigned to a variable or output.
- Let's see this with a built-in function:
::
>>> len('RPI Puckman')
11
Identify the input argument, the computation and the returned value.
A Function to Compute the Area of a Circle
------------------------------------------
- In mathematics, many functions are given as formulas. You might write a function to
calculate the area of a circle as
.. math:: a(r) = \pi r^2
- In Python, when typing directly into the interpreter, we write
::
>>> def area_circle(radius):
... pi = 3.14159
... area = pi * radius**2
... return area
- Then we can run this using
::
>>> area_circle(1)
>>> area_circle(2)
>>> r = 75.1
>>> area_circle(r)
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.
What does Python do as we type?
-------------------------------
#. Reads the keyword ``def`` and notes that a function is being defined.
- The line that starts with ``def`` is called the function *header*
#. 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 the parameter ``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 2
#. Repeats the process again at the line
::
>>> area_circle(r)
and uses the value of the variable ``r`` which is 75.1.
Flow of Control
---------------
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.
- Functions can compute many different things and return any data type Python
supports.
Arguments, Parameters and Local Variables
-----------------------------------------
- *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`` and ``area`` are *local variables* to the
function (though we should probably use the ``math`` module for pi
in the future).
- Neither ``pi`` nor ``radius`` or ``area`` exists at the top / main
level. At this level, they are ''undefined variables''. Try it out.
Exercise
---------
#. Write a function to convert the Celsius temperature to a Fahrenheit
temperature and return it.
::
>>> to_celcius(90)
32.22
#. Write a function that takes as input a string and returns a new string that frames
it with ``*``s.
::
>>> frame_word('spam and eggs')
'*****************\n* spam and eggs *\n*****************'
>>> print frame_word('spam and eggs')
*****************
* spam and eggs *
*****************
Storing Your Function In a Python File
--------------------------------------
- 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 will analyze the following program in class.
::
import math
def area_circle(radius):
area = math.pi * radius**2
return area
r = 2
a = area_circle(r)
print "Area of a circle with radius: %.1f is %.1f" %(r, a)
Functions with Multiple Arguments / Parameters
----------------------------------------------
- For our volume calculation, we write a function involving two
parameters, called with two arguments:
::
import math
def volume(radius, height):
return math.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``.
Exercises
---------
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).
In all the programs below, identify the arguments, parameters, local and global
variables?
#. Write the conversion function from Fahrenheit to Celcius in a program. Then, use this
function to read a Fahrenheit value, convert and print the result.
#. Write a function that computes the area of a rectangle. Then, write a program to use this
function.
#. Write a function that returns the middle value among three integers. Test this function
with different inputs.
More on program structure
-------------------------
- Let us revisit the program structure that will allow us to write readable programs.
- First a general comment describing the program.
- Second, all import statements.
- Third, all function definitions.
- Now, you can have the main body of your program, generally involves reading or
defining variables first, computation (including calling functions) and output.
- Well structured programs are easy to read and debug. We will work hard to help
you develop good habits early on.
Functions That Do Not Return Values
-----------------------------------
- Some Python functions do not return a value — usually they print out
their result. Use such functions very rarely for now, only if you need to repeat
the print statements many times.
- 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.
- Try and see what happens if you typed:
::
>>> print volumep(1,2)
- The choice between using functions that do and do not have return
values will become clear over time.
Functions That Call Functions
-----------------------------
- 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``:
::
import math
def area_cylinder(radius,height):
circle_area = area_circle(radius)
height_area = 2 * radius * math.pi * height
return 2*circle_area + height_area
def area_circle(radius):
return math.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.
- 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.
Thinking About What You See
---------------------------
Why is it NOT a mistake to use the same name, for example ``radius``, in
different functions (and sometimes at the top level)?
Let’s Make Some Mistakes
------------------------
In order to check our understanding, we will play around with the code
and make some mistakes on purpose
- Removing ``math`` from ``math.pi`` in one definition
- Changing the name of a function
- Switching the order of the parameters in a function call
- Making an error in our calculation
Exercise
--------
#. 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.
Why Functions?
--------------
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!
Summary
-------
- 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, :mod:`area_solid` and :mod:`area_volume`.
What to work on before next class:
----------------------------------
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*4
and 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+4
Try 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 + three
By 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 ``return`` is 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.