Week 12: Writing Classes
Week 12 Goals
-
Understand connection of instances (objects) + classes
-
Understand key attributes of class definitions
-
member variables
-
constructor
-
accessors/getters
-
mutators/setters
-
-
Define classes with basic types (int, float, …)
-
Be able to write Python classes from scratch given an English specification
Get Week 12 In-class Code
To copy over the week 12 in-class example programs, do the following (If you have trouble with either of these steps, ask a Ninja or your professor for help):
-
Create a w12-classes subdirectory in your
cs21/inclass
directory, and cd into it:$ cd ~/cs21/inclass $ mkdir w12-classes $ cd w12-classes $ pwd /home/yourusername/cs21/inclass/w12-classes
-
Copy over the week 12 files into your
w12-classes
subdirectory (check that they copied successfully copied by runningls
:$ cp ~admin21/public/w12-classes/*.py ./ $ ls employee.py employee_test.py playlist.py song.py
Week 12 Files
-
employee.py
- defines an Employee class -
employee_test.py
- code that imports and uses Employee class -
song.py
- defines and uses Song class -
playlist.py
- defines Playlist class that has a list of Songs
Object-Oriented Programming Revisited
Objects combine data and functionality (methods) together. We’ve seen lots of examples of objects in the class so far:
-
list
-
data - length, and all the data inside
-
methods - append, sort
-
-
str
-
data - each character in the string, the number of chars in the string
-
methods - isdigit, lower, split
-
-
Point
-
data - x, y
-
methods - getX, getY, draw
-
-
Circle
-
data - center, radius
-
methods - getCenter, getRadius, setFill, setOutline, setWidth, draw
-
-
StudentRecord
-
data - name, age, major, gpa
-
methods - get_name, etc.
-
-
Country
-
data - name, co2 levels, population
-
methods - getCO2, getPopulation
-
Keep in mind the following terminology:
-
class: a template for how to build objects of a new type
-
object: a particular instance of a class that has its own data values in a running program
-
dot notation: how you call the methods of a class:
<instance>.<method>(<arg1>, …)
Designing a Class
In these notes, we will define our own class to represent the employee of an organization.
In designing this class, we should consider its data (or "instance variables" or "fields") and its functionality (or "methods").
For example, our employee may include the following data:
-
name
, represented as a string -
identification number (
id
), represented as an int -
annual
salary
, represented as a float
We can use methods to allow other classes to read this data. These methods are called "accessors" or "getters" because they provide a means of accessing the data and typically start with the word "get":
-
getName
provides access to thename
-
getID
provides access to theid
-
getSalary
provides access to thesalary
We may also want to allow other classes to modify this data. These methods are called "mutators" or "setters" because they provide a means of mutating/changing the data and typically start with the word "set". In our case, we’ll say that only the name can be directly changed:
-
setName
changes thename
Another way of modifying data is to provide a means of changing it but not setting it directly. This is still considered a "mutator" because it changes the value of the field. We’ll provide a method for increasing the salary:
-
increaseSalary
increases thesalary
by a given amount
Last, there are two other important methods that are used by Python:
-
__init__
is the constructor, which is the method that is called when an object is created. It is used to initialize the fields. -
__str__
is a method that returns a string representation of this object. It is called when we use theprint()
function to print the object.
Defining a Class
Now that we’ve designed the class, we can write the code for it.
Our class will be called Employee
; it is the convention that Python class names start with uppercase letters.
The file that contains the definition of the class will be employee.py
. Although it is not required that it has the same name as the class, it makes it easy to understand, and the convention is that the file name starts with a lowercase letter.
Key to understanding the code below is the variable called self
.
This is a variable that refers to the object itself, and allows us to access its fields using dot notation, e.g. self.salary
.
You’ll notice that self
is the first parameter listed for all of these functions. Don’t forget to list it first and to use it within the function!
"""
Class to represent an employee at an organization.
This class includes the employee's name, ID, and salary.
"""
class Employee(object):
def __init__(self, name, id, salary):
"""
This is the constructor, which is the function that is called
when an instance of the class (object) is created.
Parameters:
* self: refers to this object, i.e. the object being created
* name (str): the name of the employee
* id (int): the employee's ID number
* salary (float): the employee's annual salary
Returns: None. The name, id, and salary are modified as a result.
"""
# note that we need to refer to the name instance of
# "this object" using the parameter "self"
self.name = name
self.id = id
self.salary = salary
def getName(self):
"""
Accessor ("getter") method to access the employee's name.
Parameter:
* self: refers to this object; it is implicitly passed as
an argument when this method is called
Returns: the value of the name field (str)
"""
return self.name # note that it is not simply "return name"
def setName(self, new_name):
"""
Mutator ("setter") method to change the employee's name.
Parameters:
* self: refers to this object
* new_name (str): the new name for this employee
Returns: None. The name field is modified as a result.
"""
self.name = new_name # note that it is not "name = new_name"
def getID(self):
"""
Accessor method for employee's ID.
"""
return self.id
def getSalary(self):
"""
Accessor method for employee's salary.
"""
return self.salary
def increaseSalary(self, amount):
"""
Method that increases the employee's salary by the given amount.
"""
self.salary = self.salary + amount
def __str__(self):
"""
Method that creates and returns a string representation of this object.
This allows us to print the object using the print() function.
"""
return "Name: %s; ID: %d; Salary: %.2f" % \
(self.name, self.id, self.salary)
Creating and Using Instances (Objects) of a Class
Now that we’ve defined the Employee
class, we can create instances of it in a program and then call methods on those objects.
The code below should look similar to past examples and labs that used objects, but now we are using our own custom Employee
class!
"""
Code that allows us to test the functionality of the Employee class.
"""
# this is so that we can access the Employee class in this file
from employee import *
def main():
# this creates an Employee object using the constructor
e1 = Employee("Grace Hopper", 8675309, 135000)
# these call the accessor/getter methods
print(e1.getName())
print(e1.getID())
print(e1.getSalary())
# when we pass the object to print(), it calls the __str__() method
print(e1)
# now we can call the mutator methods
e1.setName("Grace Brewster Hopper")
e1.increaseSalary(10000)
# now we should see the updated values
print(e1)
# create a separate instance/object of this class
e2 = Employee("Ada Lovelace", 1234567, 125000)
# its fields have different values from those in e1
print(e2.getName())
print(e2.getID())
print(e2.getSalary())
# when we change it, it doesn't change e2
print(e1.getSalary())
e2.increaseSalary(5000)
print(e1.getSalary()) # e1's salary has not changed
main()