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 movie 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 Movie library already written. Making sure that each new project has the latest version of a data structure or Movie 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 Movie database, working with information about movies, their titles, genres, etc.

For these tasks use the Movie class on the basis of the information given in the Movie.py (Movie class) module and the Movie_utilities.py (Movie utilities) module. Import these modules into another file for testing - do not put test code into Movie.py or Movie_utilities.py modules.

  1. Movie genres represent the various categories that movies can belong to. A movie could be a comedy, a romance, a zombie film, or a romantic zombie comedy. The Movie class defines a constant tuple of genre names called GENRES . The genres for each Movie object is stored as a list of integer indexes for the GENRES constant. Thus a romantic zombie comedy would have its genres stored as [3,4,5] . This list of integers must be converted to a string for display purposes.

    For example, the movie Dellamorte, Dellamore has the genre list [3,4,5,8] . It prints out as:

    Title:    Dellamorte Dellamore
    Year:     1994
    Director: Michele Soavi
    Rating:   7.2
    Genres:   romance, comedy, zombie, horror
    

    Complete the genres_string method for the Movie class.

    Test Movie.py:


  2. Movie genres are stored in files as a comma-delimited string. The movie Dellamorte, Dellamore has the genre list [3,4,5,8] , and it is stored in a movies file as the string " 3,4,5,8 ". When writing Movie data back to a file it must write its genres list as a string like this.

    Complete the genres_list_string method for the Movie class.

    Test Movie.py:


  3. Complete the menu function for the Movie_utilities module.

    It should print the Movie genres as:

    Genres
     0: science fiction
     1: fantasy
     2: drama
     3: romance
     4: comedy
     5: zombie
     6: action
     7: historical
     8: horror
     9: war
    

    Test Movie_utilities.py:


  4. Complete the read_genres function for the Movie_utilities module.

    It should call the menu function to display the list of genres. It must require:

    • at least one genre be entered
    • the genre code be valid
    • genres not be repeated

    Example usage:

    Genres
     0: science fiction
     1: fantasy
     2: drama
     3: romance
     4: comedy
     5: zombie
     6: action
     7: historical
     8: horror
     9: war
    Enter a genre number (ENTER to quit):
    Error: not a positive number.
    Enter a genre number (ENTER to quit): Schwarzenegger
    Error: not a positive number.
    Enter a genre number (ENTER to quit): 0
    Enter a genre number (ENTER to quit): 0
    Error: genre already chosen
    Enter a genre number (ENTER to quit): 11
    Error: input must be < 10
    Enter a genre number (ENTER to quit): 1
    Enter a genre number (ENTER to quit):
    

    The final result of the above should be the list [0, 1] .

    Test Movie_utilities.py:


  5. Complete the get_movie function for the Movie_utilities module.

    Use the following input format:

    Title: …
    Year of release: …
    Director: …
    Rating: …
    Genres
     0: science fiction
     …
    

    Test the function.

    Test Movie_utilities.py:


  6. Complete the read_movie function for the Movie_utilities module.

    Sample data:

    Dellamorte Dellamore|1994|Michele Soavi|7.2|3,4,5,8
    

    Test Movie_utilities.py:


  7. Complete the read_movies function for the Movie_utilities module.

    Test this function with the file movies.txt.

    Test Movie_utilities.py: