Classes CSCI 1133 1 What you should know by the end of lecture ● How to define your own class ● Why we define our own classes ● What the __init__ method does ● How to create objects from a user defined class ● What an instance variable is ● How to access and change instance variables ● How to define methods in a class ● How to call methods from a class 2 Classes ● Everything in Python is an object of a specific type ○ The type defines the object’s attributes and behaviors. ● A class is the blueprint from which objects are created 3 Classes (Types) vs. Objects Classes: ● int ● str ● list ● dict ● Turtle 4 Objects: ● 6 ● 'hello' ● [3, 5, 2, 1] ● {1133:'Python', 1113:'C++'} ● leo = turtle.Turtle() Why bother defining our own Class? 5 Why bother defining our own Class? ● Organization! ○ This is an excellent way to do the “data representation” step of problem solving ○ Better than a dictionary, since you can keep the data (instance variables) and algorithms (methods) relevant to a problem in the same place ■ Instance variables work across methods, avoiding the need to pass them between functions with parameters and arguments. ○ Works very well for large-scale problems, where there are different types of interconnected entities that have associated data and functions ■ Example: a video game might have a class for monsters, a class for levels, a class for collectables, a class for obstacles, etc. 6 Attributes vs. Behaviors Attributes: ● Weight ● Color ● Length ● Eye Color ● Shell Pattern ● Speed 7 Behaviors: ● Swim ● Walk ● Bite ● Look At Multiple Objects, One Class ● An instance is an specific object created from the class blueprint ○ You may create multiple instances from the same class 8 Attributes (Instance Variables) vs. Behaviors (Methods) Instance Variables: ● x ● y ● heading ● color ● size 9 Methods: ● .forward(dist) ● .right(angle) ● .pendown() ● .xcor() 10 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Consider the Student class. ● What are the instance variables of Student? ● What are the methods of Student? ● What will the code in global scope print? 11 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Consider the Student class. ● What are the instance variables of Student? ● What are the methods of Student? ● What will the code in global scope print? 12 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Consider the Student class. ● What are the instance variables of Student? ● What are the methods of Student? ● What will the code in global scope print? 13 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student 14 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student Student object 15 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student Student.__init__: self name: 'rin' scores: [90, 70] Student object 16 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student Student.__init__: self name: 'rin' scores: [90, 70] Student object .name: 'rin' 17 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student Student.__init__: self name: 'rin' scores: [90, 70] Student object .name: 'rin' .scores: [90, 70] 18 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student s1 Student object .name: 'rin' .scores: [90, 70] 19 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student s1 Student.__init__: self name: 'bob' scores: [46] Student object .name: 'rin' .scores: [90, 70] Student object 20 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student s1 Student.__init__: self name: 'bob' scores: [46] Student object .name: 'rin' .scores: [90, 70] Student object .name: 'bob' 21 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student s1 Student.__init__: self name: 'bob' scores: [46] Student object .name: 'rin' .scores: [90, 70] Student object .name: 'bob' .scores: [46] 22 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student s1 s2 Student object .name: 'rin' .scores: [90, 70] Student object .name: 'bob' .scores: [46] 23 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student s1 s2 Student object .name: 'rin' .scores: [90, 70, 80] Student object .name: 'bob' .scores: [46] 24 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student s1 s2 Student object .name: 'rin' .scores: [90, 70, 80] Student object .name: 'bob' .scores: [46, 99] 25 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student s1 s2 Student object .name: 'rin' .scores: [90, 70, 80] Student object .name: 'bob' .scores: [46, 99] 26 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student s1 s2 Student.get_average: self Student object .name: 'rin' .scores: [90, 70, 80] Student object .name: 'bob' .scores: [46, 99] 27 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student s1 s2 Student.get_average: self Student object .name: 'rin' .scores: [90, 70, 80] Student object .name: 'bob' .scores: [46, 99] 28 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student s1 s2 Student.get_average: self Student object .name: 'rin' .scores: [90, 70, 80] Student object .name: 'bob' .scores: [46, 99] 240 3 29 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student s1 s2 Student.get_average: self Student object .name: 'rin' .scores: [90, 70, 80] Student object .name: 'bob' .scores: [46, 99] 80 30 class Student: def __init__(self, name, scores): self.name = name self.scores = scores def get_average(self): return sum(self.scores)/len(self.scores) s1 = Student('rin', [90, 70]) s2 = Student('bob', [46]) s1.scores.append(80) s2.scores.append(99) print(s1.get_average()) Global: Student s1 s2 Student object .name: 'rin' .scores: [90, 70, 80] Student object .name: 'bob' .scores: [46, 99] 80 User-Defined Class ● Use the class keyword to define a class ● Classes contain methods 31 class Quad: def __init__(self,a,b,c): self.a = a self.b = b self.c = c def neg_root(self): return (-self.b-(self.b**2-4*self.a*self.c)**0.5)/(2*self.a) def pos_root(self): return (-self.b+(self.b**2-4*self.a*self.c)**0.5)/(2*self.a) Methods ● Special functions specific to a class ● Generally operate on or access objects within that class ● self is always a parameter to every method 32 class Quad: def __init__(self,a,b,c): self.a = a self.b = b self.c = c def neg_root(self): return (-self.b-(self.b**2-4*self.a*self.c)**0.5)/(2*self.a) def pos_root(self): return (-self.b+(self.b**2-4*self.a*self.c)**0.5)/(2*self.a) Method signatures The __init__ method: The Constructor ● __init__ runs whenever an object is created ● For example, bob = turtle.Turtle() runs the Turtle class’s __init__ method ● __init__ generally is used for setup, especially creating instance variables 33 class Quad: def __init__(self,a,b,c): self.a = a self.b = b self.c = c def neg_root(self): return (-self.b-(self.b**2-4*self.a*self.c)**0.5)/(2*self.a) def pos_root(self): return (-self.b+(self.b**2-4*self.a*self.c)**0.5)/(2*self.a) Creating Objects of a User-Defined Class ● Syntax is = ( ) ● Note that you don’t have to include self (since self is the object being created) 34 class Quad: def __init__(self,a,b,c): self.a = a self.b = b self.c = c eqn1 = Quad(1,1,-6) eqn2 = Quad(2,4,2) self ● The first parameter for every method should be self ● This is a pointer to the object for which the method is being called, and can be used to access instance variables, or other methods. 35 class Quad: def __init__(self,a,b,c): self.a = a self.b = b self.c = c def neg_root(self): return (-self.b-(self.b**2-4*self.a*self.c)**0.5)/(2*self.a) def pos_root(self): return (-self.b+(self.b**2-4*self.a*self.c)**0.5)/(2*self.a) Instance/Member variables/attributes ● Special variables that are stored for a given object ● Can be used/altered by any method in that object ● Use self. to reference them from within the class 36 class Quad: def __init__(self,a,b,c): self.a = a self.b = b self.c = c def neg_root(self): return (-self.b-(self.b**2-4*self.a*self.c)**0.5)/(2*self.a) def pos_root(self): return (-self.b+(self.b**2-4*self.a*self.c)**0.5)/(2*self.a) Accessing/Changing Instance Variables ● Use self. to reference them from within the class ● Use