CP164 Lab 1: Classes

Week of

This lab introduces the mechanics and practices of the CP164 labs. We assume that you have a basic grounding in using email and a web browser and working with Eclipse. If you need extra help for anything related to a lab, please talk to an IA or the Lab Instructor.


Administration

In order to work effectively in this course, you must have the following:

Part of the course work involves building a series of related programs over a number of labs and assignments. The work for one week builds on the work of previous weeks. This year's project involves writing a program to administer a food database.


Classes

A class is an object-oriented way of defining an ADT. Data and methods on the data are defined in the class. Classes provide modularity, encapsulation, information hiding, and an interface, fitting all the requirements of an ADT. We shall define classes for data (storage classes) and for data structures.

Creating Classes

A minimum Python class definition requires only two parts:

class Name:

    def __init__(self[, param,]):
        ...

Import a class with the following syntax:

from module import class

In CP164 we generally make the module name match the class name. Thus the Student class is defined in a PyDev module named Student.py.

The constructor, like all class methods (and Python functions in general), starts with the keyword def. All class methods must have at least one parameter, the self parameter. Other parameters can be defined as required, and are generally used to initialize class attributes. Class methods are indented within the class definition in order to show that they belong to the class.

The constructor is called not by using the name __init__, but by using the name of the class. Thus you create a new object with the syntax:

object = Name([argument,])

Note that even though self is shown as the first parameter to the constructor, self is never actually used as an argument. Only the rest of the constructor parameters require matching arguments.

Class attributes are generally defined within the class constructor. An attribute is defined by putting the class keyword self in front of it, as in the following example. The file number.py contains the definition of the Number class:

class Number

    def __init__(self, value):
        self.value = value
        return

and this definition can be imported into another Python module and used to define an object:

from Number import Number

example = Number(0)

This attribute may now be used anywhere within the class, but must be preceded by self. . Without self , the named value is treated as a simple variable instead. Note that in this example the parameter name value matches the attribute name. However, Python can distinguish them because the attribute is always preceded by the self keyword.


Methods

In Python most class methods are declared and used the same way as standard Python functions with the following special requirements:

The following example defines an method for the Number class:

    def square(self):
        result = self.value * self.value
        return result

then calls it from the example object:

answer = example.square()

Note that the method needs no further parameters because it is squaring and returning the value of its value attribute.

Accessing Attributes

Object attributes can be accessed simply by using the syntax:

object.attribute

The Eclipse IDE helps here by providing a drop down list of all available attributes (and methods) after typing object. , just as it does with function libraries.

You may access or change an attribute with this syntax, as in the following examples:

print(example.value)
example.value = 0
example.value = int(input("Enter a new value: "))
answer = example.value * 2

Note: There is one important exception to this. Attributes and methods that begin with ' _ ' or ' __ ' (i.e. either single or double underscores), should generally not be accessed from outside the class definition. By convention they are considered to be private attributes and methods accessible only by other class methods. We will see and use such attributes and methods when we begin working with data structures.

(Python does not have any way to make attributes and methods truly private or inaccessible from outside the class. This naming convention merely designates a status that you as a programmer should respect, in the same way that naming a constant with all capital letters does not make a Python variable truly constant, but does require you to treat it as a constant.


Project References

As we work through the term we will be creating a number of different data structures and adding more functionality to the Food library already written. Making sure that each new project has the latest version of a data structure or Food library is difficult to do if we are reduced to copying and pasting our PyDev modules into each new project. Fortunately, Eclipse provides a much better mechanism to reference code. Setting up Project References allows you to link one PyDev project to another, and to use the code from one project in another with the import and from ... import * statements already shown. Nothing needs to be changed in your source code.

To make a reference from one project to another in Eclipse, right click on a project name in the Navigator pane. From the resulting pop-up menu click on Properties and then on Project References in the resulting dialog box. You should now see the following dialog box:

references (25K)

Click on the check box of all projects that you wish to reference from the current project. In this example the project album is already selected, and the project data_structures will be added as a reference. Once this is done all of the classes in both album and data_structures will be available through import statements.

A few things to keep in mind when using project references:

At the end of this lab, you should have the following project structure in your workspace:

A Sample Project Structure

(Of course, the projects should be using your login.)

The assignment validator assumes you will have a login_data_structures project in your .zip file.

This term we will be writing programs and functions related to running a food database, working with information about food, its name, origin, etc.

For these tasks use the food class on the basis of the information given in the Food.py class code and the Food_utilities.py module. Import these modules into another file for testing. (You do not have to complete all of the utility functions in the lab, but you should eliminate any errors or warnings in the code.)

Put Food.py and Food_utilities.py in your login_data_structures project so that you have only one copy of each file, and so that they can be referenced from other projects.

  1. Complete the origins method for the Food module.

    Test Food.py:


  2. Complete the __str__ method for the Food module.

    Test Food.py:


  3. Complete the get_food function for the Food_utilities module.

    Use the following input format:

    Name:
    Origin
     0 Canadian
     1 Chinese
     2 Indian
     …
    :
    Vegetarian (Y/N):
    Calories:
    

    Test this function by printing out the resulting Food object.

    Test Food_utilities.py:


  4. Complete the read_food function for the Food_utilities module.

    Sample data:

    Spanakopita|5|True|260
    

    Test Food_utilities.py:


  5. Complete the read_foods function for the Food_utilities module.

    Test this function with the file foods.txt.

    Test Food_utilities.py:


  6. Complete the write_foods function for the Food_utilities module.

    The resulting file should have the same format as the file foods.txt . In Eclipse, right click on the lab 1 project name and choose, Refresh in order to see the new file in the project manage.

    Test this function by writing the contents of the list from the previous task to a file named new_foods.txt.

    Test Food_utilities.py:


  7. Complete the get_vegetarian function for the Food_utilities module.

    Test this function by selecting and printing all the vegetarian foods in the foods.txt file.

    Test Food_utilities.py: