class Animal(object) :
def __init__(self, age) :
self.age = age
self.name = None
# name is a data attribute
# even though an instance is not initialized with it as a parameter
def get_age(self) : # getter
return self.age
def get_name(self) : # getter
return self.name
def set_age(self, newage) : # setter
self.age = newage
def set_name(self, newname = "") : # setter
self.name = newname
def __str__(self) :
return "animal:"+str(self.name)+":"+str(self.age)
Author of class definition may change data attribute variable name
: if you are accessing data attributes outside the class and class definition changes, may get errors
Python is not greate at information hiding
: allows you to access/write/create data attributes
: it's not good style
Use Setter/Getter
: do not directly access attributes
: good style
: easy to maintain code
: prevents bugs
Defualt Arguments
: used if no actual argument is given
...
def set_name(self, newname = "") : # setter
self.name = newname**
...
a = Animal(3)
a.set_name()
print(a.get_name()) # prints ""
a = Animal(3)
a.set_name("fluffy")
print(a.get_name()) # prints fluffy
class Animal(object) :
def __init__(self, age) :
self.age = age
self.name = None
def get_age(self) : # getter
return self.age
def get_name(self) : # getter
return self.name
def set_age(self, newage) : # setter
self.age = newage
def set_name(self, newname = "") : # setter
self.name = newname
def __str__(self) :
return "animal:"+str(self.name)+":"+str(self.age)
class Cat(Animal) : # inherits all attributes of Animal
def speak(self) : # add new functionality via speak method
print("meow")
def __str__(self) : # overrides __str__
return "cat:" + str(self.name) + ":" + str(self.age)
Add new functionality with speak()
: instance of type Cat can be called with new methods
: instance of type Animal throws error if called with Cat's new method
__init__ is not missing, uses the Animal
Subclass can have methods with same name as superclass
: for an instance of a class, look for a method name in current class definition
: if not found, look for method name up the hierarchy
: use first method up the hierarchy that you found with that method
Example of Inheritance
class Animal(object) :
def __init__(self, age) :
self.age = age
self.name = None
def get_age(self) : # getter
return self.age
def get_name(self) : # getter
return self.name
def set_age(self, newage) : # setter
self.age = newage
def set_name(self, newname = "") : # setter
self.name = newname
def __str__(self) :
return "animal:"+str(self.name)+":"+str(self.age)
class Person(Animal) :
def __init__(self, name, age) :
Animal.__init__(self, age) # Call Animal constructor
self.set_name() # call Animal's method
self.friends = [] # add a new data attribute
def get_friends(self) :
return self.friends
def add_friend(self, fname) :
if fname not in self.friends :
self.friends.append(fname)
def speak(self) :
print("hello")
def age_diff(self, other) :
diff = self.age - other.age
print(abs(diff), "year difference")
def __str__(self) :
return "person:" + str(self.name) + ":" + str(self.age)
# overrides Animal's method
import random
class Student(Person) :
def __init__ (self, name, age, major_None) :
Person.__init__ (self, name, age)
self.major = major
def change_major(self, major) :
self.major = major
def speak(self) :
r = random.random()
if r < 0.25 :
print("I have homework")
elif 0.25 <= r < 0.5 :
print("i need sleep")
elif 0.5 <= r < 0.75 :
print("i should eat")
else :
print("i am watching tv")
def __str__(self) :
return "student:"+str(self.name)+":"+str(self.age)+":"+str(self.major)
class Animal(object) :
def __init__(self, age) :
self.age = age
self.name = None
def get_age(self) : # getter
return self.age
def get_name(self) : # getter
return self.name
def set_age(self, newage) : # setter
self.age = newage
def set_name(self, newname = "") : # setter
self.name = newname
def __str__(self) :
return "animal:"+str(self.name)+":"+str(self.age)
class Rabbit(Animal) :
tag = 1 # class variables
def __init__(self, age, parent1 = None, parent2 = None) :
Animal.__init__(self, age)
self.parent1 = parent1
self.parent2 = parent2
self.rid = Rabbit.tag # instance variable rid, Rabbit.tag access class variable
Rabbit.tag += 1
# incrementing class var. changes it for all instances that may reference it
def get_rid(self) :
return str(self.rid).zfill(3)
# zfill method is on a string to pad the beginning with zeros
# for example, 001 not 1
def get_parent1(self) :
return self.parent1
def get_parent2(self) :
return self.parent2
def __add__(self, other) :
# returning object of same type as this class
return Rabbit(0, self, other)
# recall Rabbit's __init__(self, age, parent1 = None, parent2 = None)
# age goes to 0, parent1 goes to self, parent2 goes to other
def __eq__ (self, other) :
parents_same = self.parent1.rid == other.parent1.rid \
and self.parent2.rid == other.parent2.rid
parents_opposite = self.parent2.rid == other.parent1.rid \
and self.parent1.rid == other.parent2.rid
return parents_same or parents_opposite