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

  • A 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
    

    Can you 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

    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?

  1. Reads the keyword def and notes that a function is being defined.

    • The line that starts with def is called the function header
  2. Reads the rest of the function definition, checking its syntax

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

  4. 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
  5. Repeats the process of running the function at the line

    >>> area_circle(2)
    

    this time with radius assigned the value 2

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

  1. Write a function to convert the Celsius temperature to a Fahrenheit temperature and return it.

    >>> to_celsius(90)
    32.22
    
  2. 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

  • In practice we rarely type our functions directly into the interpreter. Instead, we type the function into a file along with the rest of the program, save the file, and then run the program.

    • 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).

  1. Write a function to convert from Fahrenheit to Celsius. Then, below the function, write code that reads a Fahrenheit value, calls the function to make the conversion, and prints the result.
  2. Write a function that computes the area of a rectangle. Then, write code to demonstrate the use of this function.
  3. Write a function that returns the middle value among three integers. (Hint: make use of min() and max().) Write code to test this function with different inputs.

For each program, identify the arguments, the parameters, the local variables and the global variables.

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.

  • For example,

    import math
    
    def volumep(r, h):
        vol =  math.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_circle(radius):
        return math.pi * radius ** 2
    
    def area_cylinder(radius,height):
        circle_area = area_circle(radius)
        height_area = 2 * radius * math.pi * height
        return 2*circle_area + height_area
    
    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:

    1. Starting at the first print at the top level, into area_circle and back.
    2. At the third print
      1. into area_cylinder,
      2. into area_circle,
      3. back to area_cylinder, and
      4. 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

  1. Write a function to compute the area of a rectangle.
  2. 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, area_solid and 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. 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. By next class, make sure all of this is quite easy to do without consulting the course notes.