CS30 - Spring 2015 - Class 15
Example code in this lecture
person.py
rectangle.py
rectangle2.py
queue.py
stack.py
Lecture notes
administrative
- assignment 5 back soon
- assignment 6 due tomorrow
- be clear and concise
- analyze three things:
- performance (both training error and testing error, where appropriate)
- reliability: how often does it achieve that performance
- convergence: how quickly does it get there
- nested for loop
objects
- objects have two pieces of information:
- data
- methods
- for example, a list is an object
>>> l = [1, 2, 3, 4]
>>> l.append(5)
>>> l
[1, 2, 3, 4, 5]
>>> l.reverse()
>>> l
[5, 4, 3, 2, 1]
method types
- there are two types of methods:
- mutator methods (the book calls these "modifiers")
- change or mutate the object
- accessor methods (the book calls these "pure functions")
- do not change the object
- ask questions about the object
- you can look at all of the methods available for an object using help:
>>> help(l)
or
>>> help(list) # the type of the object
constructors
- every object has a special method called a constructor
- it has the same name as the type of the object and can be called on it's own to "construct" a new object
- Many of the methods we've actually been using already are actually constructors!
>>> str(10)
'10'
>>> int("10")
10
>>> float(10)
10.0
- all of these construct a new object of that type
- Some things (like lists and tuples) have special ways of constructing them, but they too also have constructors
>>> list()
[]
>>> tuple()
()
>>> list( "abcde" )
['a', 'b', 'c', 'd', 'e']
>>> tuple( "abcde" )
('a', 'b', 'c', 'd', 'e')
>>> tuple( [1, 2, 3, 4] )
(1, 2, 3, 4)
classes
- a "class" is the blueprint describing what data and methods an object will have
- an object is an instance of a class
- for example, we could define a class people
- people have attributes
- people will have methods
- when we define a particular person, it is an object that is an instance of the class or people
- classes define types
- in Python, since all things are objects, then they all represent instances of objects
- though in other languages, you could have a type that is not defined by a class
defining our own classes
- syntax:
class name_of_class:
# methods in the class
- look at Person class in
person.py code
- 5 methods
- 2 "special" methods
- methods that are surrounded by two underscores on each side are "special" methods
- they are generally NOT called directly
- __init__ defines the constructor for the method
- __str__ defines what the object will be when it's printed
- self
- self is a variable that allows us to store data and retrieve data in an object
- self is a reference to the current object
- it should be the first parameter to every method in a class (not totally true, but fine for this class)
- though you do NOT include it when you call the methods (this is a little annoying, but you'll get used to it)
- look at the constructor (__init__ method) in
person.py code
- takes self and two parameters
- all it does is SAVE these parameters into the object
- look at the "get_" methods in
person.py code
- these are accessor methods
- give us information back
- notice they only take self as a parameter and use that to give back characteristics about the object
- look at the "change_shirt" method
write a class called Rectangle
- that has a constructor that takes x1, y1, x2, y2 (and self)
- and one method called area that gives back the area of the rectangle
look at the Rectangle class in
rectangle.py code
- many different ways we could have implemented this
- in this version, I chose to store the two points as x, y pairs, specifically 4 instance variables:
self.x1
self.y1
self.x2
self.y2
- init
- just saves away the input parameters into instance variables so we can use them later
self.x1 = x1
says take the parameter x1 and put its value into the instance variable self.x1
- this creates 4 instance variables
- area
- uses the four instance variables to calculate the width and height of the rectangle
- we need to use abs since we don't specify that the x,y pairs are lower left and upper right corners
why classes?
- encapsulation
- look at the Rectangle class in
rectangle2.py code
- we have the exact same set of methods (constructor and area)
- however, we have *different* internal representation
- we store the lower left hand corner (x,y)
- and the width and height of the rectangle
- notice that we can ask the exact same questions using this representation
- anyone using the Rectangle class should NOT care which version we use
- both have the same set of methods and the same functionality
- this is the power of using classes, a general framework called object-oriented programming
- modularity
- functions create single units that we can use to build up other functions
- in the same way, classes allow us to create functional units (in this cases a class of objects with a particular behavior)
- avoid naming conflicts
look at queue class in
queue.py code
- has 5 methods (constructor, str, and three methods we wrote
- what data does it keep, i.e. what are the instance variables?
- just self.queue, which is a list
- constructor
- the constructor has an optional parameter and can be called with either zero parameters or with a list:
>>> q = Queue()
>>> print q
The queue contains: []
>>> q = Queue([1, 2, 3, 4])
>>> print q
The queue contains: [1, 2, 3, 4]
- if it's given a list as a parameter it *copies* it using slicing (:) and saves that away in the instance variable
- why copy it?
- to avoid aliasing!
- otherwise, the instance variables (self.queue) would reference the same list as was passed in (a bad thing!)
- look at enqueue and dequeue. What is this class?
- way of storing data
- implemented like a line
- first things to be enqueued (added) are the first things to be dequeued (removed)
- sometimes called FIFO (first in first out)
- enqueue adds elements to the *back* of the list
- dequeue removes elements from the *front* of the list
- Example usage:
>>> q = Queue()
>>> q.enqueue(1)
>>> q.enqueue(10)
>>> q.enqueue(2)
>>> print q
The queue contains: [1, 10, 2]
>>> q.dequeue()
1
>>> q.dequeue()
10
>>> q.dequeue()
2
- is_empty
- just checks if the queue has anything in it
- notice that underneath the covers, this is still just a list
- by hiding the list in the class, we have:
- provided a clear small set of methods that defines how we can interact with the object (the queue)
- hid the implementation details from whoever uses it
- we used a list, but could have used something else
- in a similar way, we could have added to the front of the list and removed from the back and still achieved exactly the same functionality
look at Stack class in
stack.py code
- what does it do?
- same basic interface as the Queue class
- constructor and str methods
- is_empty
- a method to add things (push)
- a method to remove things (pop)
- the difference is that stacks add and remove things from the *same* end of the list
- think of it like a stack of plates
- the last plate that you put on top
- will be the first one to be removed
- sometimes called LIFO (last in first out)
- For example, if we add the same elements as we did before, we get them in the opposite order
>>> s = Stack()
>>> s.push(1)
>>> s.push(10)
>>> s.push(2)
>>> s.pop()
2
>>> s.pop()
10
>>> s.pop()
1