Classes + Objects
CS106A, Stanford University
Housekeeping
• Hope you're well!
• The Stanford Honor Code
– CS106A retraction policy
• Wrote my own code, got help from LaIR/staff → good
• Looked up how a particular function worked online → good
• Talked with my friends about strategies/approaches → good
• Copied solution code from another source/person → bad
• Friend and I collaborated on one solution and both turned it in → bad
– Be honest with yourself about what happened
– Deadline to retract any assignments: May 27th
Review: Sorting
Basic Sorting
• The sorted function orders elements in a collection in
increasing (non-decreasing) order
– Can sort any type that support < and == operations
– For example: int, float, string
– sorted returns new collection (original collection unchanged)
>>> nums = [8, 42, 4, 8, 15, 16]
>>> sorted_list = sorted(nums)
>>> sorted_list
[4, 8, 8, 15, 16, 42]
Intermediate Sorting
• Can sort elements in decreasing (non-increasing) order
– Use the optional parameter reverse=True
>>> nums = [8, 42, 4, 8, 15, 16]
>>> sorted(nums, reverse=True)
[42, 16, 15, 8, 8, 4]
>>> strs = ['banana', 'CHERRY', 'apple', 'donut']
>>> sorted(strs, reverse=True)
['donut', 'banana', 'apple', 'CHERRY']
• Note case sensitivity of sorting strings!
– Any uppercase letter is less than any lowercase letter
– For example: 'Z' < 'a'
Advanced Sorting
• Sorting using a custom function
– Use the optional parameter key=<function name>
– Elements sorted based on value returned from key function
def get_len(s):
return len(s)
def main():
strs = ['a', 'bbbb', 'cc', 'zzz']
sorted_strs = sorted(strs, key=get_len)
print(sorted_strs)
Output:
['a', 'cc', 'zzz', 'bbbb']
Super Deluxe Advanced Sorting
• Sorting a list of tuples with a custom function
– Use the optional parameter key=<function name>
def get_count(food):
return food[1]
def main():
foods = [('apple', 5), ('banana', 2), ('chocolate', 137)]
sort_names = sorted(foods)
print(sort_names)
sort_count = sorted(foods, key=get_count)
print(sort_count)
rev_sort_count = sorted(foods, key=get_count, reverse=True)
print(rev_sort_count)
Output:
[('apple', 5), ('banana', 2), ('chocolate', 137)]
[('banana', 2), ('apple', 5), ('chocolate', 137)]
[('chocolate', 137), ('apple', 5), ('banana', 2)]
( , , , )
Yes, that's in sorted order!
Learning Goals
1. Learning about Object-Oriented Programming
2. Writing code using Classes and Objects in Python
Object-Oriented Programming
(OOP)
It's not a mistake!
Object-Oriented Programming
• There are different paradigms in programming
• So far, you've learned imperative programming
– Provide series of direct commands for program execution
– Commands are changing the program's state
• Object-oriented programming
– Define objects that contain data and behavior (functions)
– Program is (mostly) an interaction between objects
– You are calling functions of objects (called "methods")
• Python allows for programming in either paradigm!
– Other programming paradigms exist, but we won't talk
about those in this class
What are Classes and Objects?
• Classes are like blueprints
– They provide a template for a kind of object
– They define a new type
– E.g., "Human" would be a class
• Generally, have two arms, have two legs, breathe air, etc.
• Objects are instances of Classes
– Can have multiple objects of the same Class type
– E.g., You would be an instance of the Human class
• So, you have the properties of your Class (Human)
– There are lots of other people out there too
• You are all of type "Human"
• You are all objects of the same Class
Example of a Class in Python
• Let's create a Counter class
– Can ask is for the "next" ticket number
– Need to keep track of next ticket number
– Class names start with Uppercase character
– No main() function (Class is not a program)
class Counter:
# Constructor Two (or double) underscores – called "dunder" for short
def __init__(self):
self.ticket_num = 0 # "instance" variable
# Method (function) that returns next ticket value
def next_value(self):
self.ticket_num += 1
return self.ticket_num
Let's See It In Action:
counter.py
Objects are Mutable
• When you pass an object as a parameter, changes to
object in that function persist after function ends
from counter import Counter # import the Class
def count_two_times(count):
for i in range(2):
print(count.next_value())
def main():
count1 = Counter()
Output: Count1:
count2 = Counter()
1
print('Count1: ') 2
count_two_times(count1) Count2:
1
print('Count2: ') 2
count_two_times(count2) Count1:
print('Count1: ') 3
count_two_times(count1) 4
General Form for Writing a Class
• Filename for class is usually classname.py
– Filename is usually lowercase version of class name in file
class Classname:
# Constructor
def __init__(self, additional parameters):
body
self.variable_name = value # example instance variable
# Method
def method_name(self, additional parameters):
body
Constructor of a Class
• Constructor
– Syntax:
def __init__(self, additional parameters):
body
• Called when a new object is being created
– Does not explicitly specify a return value
– New object is created and returned
• Can think of constructor as the "factory" that creates
new objects
– Responsible for initializing object (setting initial values)
– Generally, where instance variables are created (with self)
self.variable_name = value # create instance variable
Instance Variables
• Instance variables are variable associated with objects
– Each object get its own set of instance variables
– Generally, they are initialized in constructor for class
– Instance variables accessed using self:
self.variable_name = value
– Self really refers to the object that a method is called on
def main():
count1 = Counter()
count2 = Counter()
x = count1.next_value()
y = count2.next_value()
Instance Variables
• Instance variables are variable associated with objects
– Each object get its own set of instance variables
– Generally, they are initialized in constructor for class
– Instance variables accessed using self:
self.variable_name = value
– Self really refers to the object that a method is called on
def main(): def __init__(self):
count1 = Counter() self.ticket_num = 0
count2 = Counter()
x = count1.next_value()
y = count2.next_value()
count1
self.ticket_num 0
Instance Variables
• Instance variables are variable associated with objects
– Each object get its own set of instance variables
– Generally, they are initialized in constructor for class
– Instance variables accessed using self:
self.variable_name = value
– Self really refers to the object that a method is called on
def main():
count1 = Counter()
count2 = Counter()
x = count1.next_value()
y = count2.next_value()
count1
self.ticket_num 0
Instance Variables
• Instance variables are variable associated with objects
– Each object get its own set of instance variables
– Generally, they are initialized in constructor for class
– Instance variables accessed using self:
self.variable_name = value
– Self really refers to the object that a method is called on
def main(): def __init__(self):
count1 = Counter() self.ticket_num = 0
count2 = Counter()
x = count1.next_value()
y = count2.next_value()
count1
self.ticket_num 0
count2
self.ticket_num 0
Instance Variables
• Instance variables are variable associated with objects
– Each object get its own set of instance variables
– Generally, they are initialized in constructor for class
– Instance variables accessed using self:
self.variable_name = value
– Self really refers to the object that a method is called on
def main():
count1 = Counter()
count2 = Counter()
x = count1.next_value()
y = count2.next_value()
count1
self.ticket_num 0
count2
self.ticket_num 0
Instance Variables
• Instance variables are variable associated with objects
– Each object get its own set of instance variables
– Generally, they are initialized in constructor for class
– Instance variables accessed using self:
self.variable_name = value
– Self really refers to the object that a method is called on
count1
def main():
count1 = Counter()
def next_value(self):
count2 = Counter()
self.ticket_num += 1
x = count1.next_value()
return self.ticket_num
y = count2.next_value()
count1
self.ticket_num 0
count2
self.ticket_num 0
Instance Variables
• Instance variables are variable associated with objects
– Each object get its own set of instance variables
– Generally, they are initialized in constructor for class
– Instance variables accessed using self:
self.variable_name = value
– Self really refers to the object that a method is called on
count1
def main():
count1 = Counter()
def next_value(self):
count2 = Counter()
self.ticket_num += 1
x = count1.next_value()
return self.ticket_num
y = count2.next_value()
count1
self.ticket_num 1
count2
self.ticket_num 0
Instance Variables
• Instance variables are variable associated with objects
– Each object get its own set of instance variables
– Generally, they are initialized in constructor for class
– Instance variables accessed using self:
self.variable_name = value
– Self really refers to the object that a method is called on
def main():
count1 = Counter()
count2 = Counter()
x = count1.next_value()
y = count2.next_value()
count1
self.ticket_num 1
count2
self.ticket_num 0
Instance Variables
• Instance variables are variable associated with objects
– Each object get its own set of instance variables
– Generally, they are initialized in constructor for class
– Instance variables accessed using self:
self.variable_name = value
– Self really refers to the object that a method is called on
count2
def main():
count1 = Counter()
def next_value(self):
count2 = Counter()
self.ticket_num += 1
x = count1.next_value()
return self.ticket_num
y = count2.next_value()
count1
self.ticket_num 1
count2
self.ticket_num 0
Instance Variables
• Instance variables are variable associated with objects
– Each object get its own set of instance variables
– Generally, they are initialized in constructor for class
– Instance variables accessed using self:
self.variable_name = value
– Self really refers to the object that a method is called on
count2
def main():
count1 = Counter()
def next_value(self):
count2 = Counter()
self.ticket_num += 1
x = count1.next_value()
return self.ticket_num
y = count2.next_value()
count1
self.ticket_num 1
count2
self.ticket_num 1
Instance Variables
• Instance variables are variable associated with objects
– Each object get its own set of instance variables
– Generally, they are initialized in constructor for class
– Instance variables accessed using self:
self.variable_name = value
– Self really refers to the object that a method is called on
def main():
count1 = Counter()
count2 = Counter()
x = count1.next_value()
y = count2.next_value()
count1
self.ticket_num 1
count2
self.ticket_num 1
Methods (Functions) in Class
• Methods (name used for functions in objects)
– Syntax:
def method_name(self, additional parameters):
body
• Works like a regular function in Python
– Can return values (like a regular function)
– Has access to instance variables (through self):
self.variable_name = value
– Called using an object:
object_name.method_name(additional parameters)
– Recall, parameter self is automatically set by Python as the
object that this method is being called on
• You write: number = count1.next_value()
• Python treats it as: number = next_value(count1)
Another Example: Students
• Want a Class to keep track information for Students
– Each student has information:
• Name
• ID number
• Units completed
– Want to specify a name and ID number when creating a
student object
• Initially, units completed set to 0
– Student's number of units completed can be updated over
time
– Also want to be able to check if a student can graduate
• Student needs to have at least UNITS_TO_GRADUATE units
Bring Me the Students!
student.py
Learning Goals
1. Learning about Object-Oriented Programming
2. Writing code using Classes and Objects in Python