Python MIT OCW Lec9 : Python Classes and Inheritance

김재만·2023년 9월 20일
0

Python MIT OCW

목록 보기
9/9

배울 내용

  1. More on classes
    : getters and setters
    : information hiding
    : class variables
  2. Inheritance

1. Getter And Setter Methods

  • See this code
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)

Information Hiding

  • 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

2. Hierarchies

  • Parent class
    : Superclass
  • Child class
    : Subclass
    : inherits all data and behavior of parent class
    : add more info
    : add more behavior
    : override behavior
  • 위에서 정의된 Animal Class를 그대로 사용한다. 다음 코드를 보자.
 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)

3. Class Variables

  • Class variables and their values are shared btw all instances of a class
  • See this code
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

4. Rabbit Example : Special Method

__add__

  • define + operator btw two Rabbit instances
    : define what something like this does : r4 = r1 + r2 where r1 and r2 are Rabbit instances
    : r4 is a new Rabbit instance with age 0
    : r4 has self as one aprent and other as the other parent
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

__eq__

  • Decide that two rabbits are equal if they have the same two parents
  • Compare ids of parents since ids are unique
  • note that you can't compare objects directly
    : ex) self.parent1 == other.parent1 (x)
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
profile
Hardware Engineer가 되자

0개의 댓글