CS8, Fall 2010

lab02: ("lab two")
Test-driven development
of functions that return values

Goals for this lab

By the time you have completed this lab, you should be able to

This lab will also reinforce some lessons from lab01

Step by Step Instructions

Step 0: Get together with your pair partner, and register on Gauchospace.

As with lab01, lab02 is a Pair Partner lab.

Just like last time, we are asking you to find times that you can work together outside of class, and make a commitment to those times—and post those times on a discussion board on Gauchospace.

If you do not have a pair partner, please contact your TA and/or instructor for assistance.

Step 1: Choose a driver/navigator

Next, you need to choose an initial driver and a navigator. You will start your work in the driver's account—and switch half way through. When you switch, you'll copy the files just to make sure you both have a copy of the files in each of your accounts.

The driver should log on to her/his CSIL account just as you did for lab00 and lab01.

Step 2: Create a directory for lab02

Note: these instructions assume you are working in Cooper or CSIL—if you are working on your own PC or Mac, you'll need to adapt these instructions to your situation.

First, create a directory (folder) called lab02, inside your cs8 folder, which is in turn, inside your home directory.

A short way to say that is: create a directory ~/cs8/lab02

There are two ways to do it:

If you've forgotten how, consult the instructions for lab00. If you still can't figure it out, you may ask a classmate, or the TA or instructor for help.

(Note: eventually, I'll stop spelling this out in so much detail—I'll just say: create a ~/cs8/lab03 directory, for example, and expect that you'll know how to do that. For at least one more lab, though, I'll hold your hand through the process. By the time you get to cs24 and beyond, you'll likely be expect to just know that you should create a separate folder for each of your assignments.)

By the way... something you should read and know for the exam:

We learned up above that ~ by itself is a symbol for your home directory.

As an example, ~/cs8/lab02/myFunctions.py means: go into my home directory, then into cs8, then into lab02, then look at the file myFunctions.py

If we put a name after the tilde, we can access someone else's home directory. So, ~pconrad/cs8/cs8idle means "look for a file cs8idle inside a directory cs8 inside pconrad's home directory".

Note that ~pconrad/cs8/cs8idle and ~/pconrad/cs8/cs8idle are not the same.

For the exam: be able to explain the difference between ~pconrad/cs8 and ~/pconrad/cs8

Step 2: Bring up IDLE, and a window for function definitions

To bring up IDLE, type this command in the Terminal window, just like we did last week:


When you do, you should see the IDLE program come up. The window that appears should have the Python Command prompt (>>>) in it.

Next, in IDLE, select "File=>New Window" to open a new "untitled" window for Python code.

When it comes up, click and drag the window by its title bar over to the right of your Python Shell window.

Here's what that looks like:

Selecting File=>New Window The "untitled" window appearing Dragging the windows so they are side-by-side
Selecting File => New Window in IDLE New window appears New windows side by side

Once you've opened that file, add a comment to the top of your file like this one (substituting your own name and the current date in the proper spot):

# lab02.py  by Agnes Nitt and Jason Ogg for CS8 lab02,  08/12/2010
# Some Example Python Functions

Then, save it under the name lab02.py

Note: eventually, with this as well, I'll stop spelling this out in so much detail—I'll just say: start a new Python file called lab02.py. I'll expect you to know that this means: open IDLE, bring up the New Window, and start by putting a header comment at the top, with your name, date, the name of the assignment, and a one line description of what the file is for.

For at least one more lab, though, I'll hold your hand through the process.

By the time you get to cs24 and beyond, there will be an expectation that you are used to all this—once you've been shown once how to use the basic tools of a programming environment, you'll be able to just bring up those tools, start a new file (with header comment at the top), and get to work.

Now proceed with Step 3.

Step 3. Learning about Print vs. Return

The next step is to examine a few things about print vs. return.

We are going to define two functions in our function window—both of which calculate the square of a number—i.e. the number multiplied by itself.

One will do it using print, and the other using return.

At first, the two functions will seem to be identical. But as we'll discover, there is a big difference between them.

In the window you created for lab02.py, enter these two function definitions after your comment, so that the file looks like this:

# lab02.py  by Agnes Nitt and Jason Ogg for CS8 lab01,  08/12/2010
# Some Example Python Functions

# a function that returns the square of a number def square(x): return (x * x) # a function that prints the square of a number def sqr(x): print (x * x)

Ask yourself—what is the difference between these two functions?

Then, choose the "Run" command from the menu. In your Python shell window, you should see output similar to the following:

>>> ================================ RESTART ================================

At this prompt, you can now type function calls to the two functions you've defined. Try these:

>>> square(5)
>>> sqr(5)
>>> square(3)
>>> sqr(3)

At the moment, it may appear that there is no difference between return and print—they both do the same thing.

But, then, try this:

>>> square(5) + square(5)

As you can see, the result is 50—because 5 squared is 25, and if you add 25 + 25, you get 50.

But compare this:

>>> sqr(5) + sqr(5)
Traceback (most recent call last):
  File "", line 1, in 
    sqr(5) + sqr(5)
TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'

Here, you get a completely different result! So, clearly, there is a big difference between return and print inside a function.

The difference is this:

So, square(5) + square(5) becomes 25 + 25, because square(5) returns the value 5 * 5, i.e. 25.

But, when a function doesn't return anything, the function call gets replaced with a value that has something called "NoneType".

So sqr(5) + sqr(5) becomes something like NoneType + NoneType, and Python doesn't know how to handle that. Yes, the values 25 and 25 get printed, but not in any way that is useful.

This is why we will emphasize writing functions that return values rather than print values—they are generally more useful, because they can be reused inside other expressions.

Try a few more examples to illustrate the idea:

>>> square(3) + square(4)
>>> sqr(3) + sqr(4)
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
sqr(3) + sqr(4)
TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'
>>> square(square(2)) 16 >>> sqr(sqr(2)) 4 Traceback (most recent call last): File "", line 1, in sqr(sqr(2)) File "/Users/bob/Documents/lab02.py", line 11, in sqr print (x * x) TypeError: unsupported operand type(s) for *: 'NoneType' and 'NoneType' >>> square(square(square(2))) 256 >>>

When you think you understand the difference, move on to the next step. If you don't understand the difference, try to figure it out some more—or make a note to ask about it in lecture, or office hours—this is an important concept and will definitely be on the next midterm exam!

If it isn't crystal clear yet, you can still proceed with the rest of today's lab, but certainly come back and ask about this as soon as you can.

Step 4. Copying some code from the web

The starting point for this weeks lab can be found at this link:


Open that link, and copy the contents into the window you opened for your lab02.py file.

Then, choose Run => Run Module, and see the output.

It should look something like this:

>>> ================================ RESTART ================================
Test perimRect test 1 passed.
Test perimRect test 2 passed.
Test perimRect test 3 passed.
Test FtoC test 1 failed! expected result: 100 actual result: 194.222222222
Test FtoC test 2 failed! expected result: 0 actual result: 14.2222222222
Test FtoC test 3 failed! expected result: 20 actual result: 50.2222222222
Test areaRect test 1 failed! expected result: 6 actual result: -1
Test areaRect test 2 failed! expected result: 10 actual result: -1
Test areaRect test 3 failed! expected result: 9 actual result: -1

We can see that three tests passed for the perimRect function, but all the rest of the tests failed. So, we have some work to do.

Step 4: The idea

The idea here is that the function check_expect can be used to test whether a function works correctly or not.

Take a look at the function definition for check_expect.

Look at the code for a moment, and see if you can see this in the code.

def check_expect(testLabel,check,expect):
    if (check == expect):
        print ("Test " + testLabel + " passed.")
        print ("Test " + testLabel 
               + " failed! expected result: " + str(expect) 
               + " actual result: " + str(check))


There may be a few things here that are unfamiliar:

But don't worry too much about those details—the main thing is the big picture. And the big picture is that the check_expect function is one that helps us test other functions to see if they work properly.

Look in the code you have in your window, and find the following section:

def perimRect(length,width):
        return 2 * length + 2 * width


This is a function that should return (not print!) the perimeter of a rectangle—the formula is double the length plus double the width.

We then see some "test cases", that look like this:

check_expect("perimRect test 1", perimRect(2, 3), 10)
check_expect("perimRect test 2", perimRect(4, 2.5), 13)
check_expect("perimRect test 3", perimRect(3, 3), 12)

The idea is that each call to check_expect has three parameters:

You can see that testLabel, check, and expect correspond to the three parameters of the check_expect function definition:

def check_expect(testLabel,check,expect):

This is always true in Python programming: the parameters in the function call need to correspond exactly with the parameters in the function definition.

So, what's happening in this lab is the following:

Each of the places that you find some @@@ comments, your job is to follow the instructions there, and then remove the comment with the @@@ signs in it.

When your file passes all the tests, and you've correctly removed all the comments that have @@@ lines in them, you are almost finished and ready to submit!

Here's an example of what the finished output would look like (note the additional tests that have been added):

Test perimRect test 1 passed.
Test perimRect test 2 passed.
Test perimRect test 3 passed.
Test perimRect test 4 passed.
Test perimRect test 5 passed.
Test FtoC test 1 passed.
Test FtoC test 2 passed.
Test FtoC test 3 passed.
Test FtoC test 4 passed.
Test areaRect test 1 passed.
Test areaRect test 2 passed.
Test areaRect test 3 passed.
Test areaRect test 4 passed.
Test CtoF test 1 passed.
Test CtoF test 2 passed.
Test CtoF test 3 passed.
Test CtoF test 4 passed.

If you get output like that—and you've replaced all the @@@ comments in your code with the proper stuff, you are almost ready to submit!

But first, do a visual inspection of your code to double check that you did everything you were asked to do... that is Step 5.

Step 5: Check over your program to see if it is ready to submit

Before you submit your assignment, check these things:

Step 6 : Submit your assignment using the turnin program on CSIL

To submit your assignment, we use the cd command that we practiced earlier:

-bash-3.00$ cd 
-bash-3.00$ pwd 

-bash-3.00$ cd cs8 
-bash-3.00$ pwd 

When you are in inside your cs8 directory, you are ready for the turnin step.

Type the following at the prompt:

turnin lab02@cs8 lab02

You should be asked if you want to turn in this program. Respond "yes", and then you should get a message indicating that your efforts were successful!

Note: Starting with the next lab, I won't spell this out in so much detail. I'll just say something like

You'll be expected to know what to do. Eventually, even that will be whittled down to:

Evaluation and Grading Rubric (200 pts)

Due Date: Friday, October 8, 5pm


Copyright 2010, Phillip T. Conrad, CS Dept, UC Santa Barbara. Permission to copy for non-commercial, non-profit, educational purposes granted, provided appropriate credit is given; all other rights reserved.