Object Oriented Programming with Python

Sachin Joshi

Research Computing

Basics of Object-Oriented Programming

  • What is OOP?
  • Classes in Python
  • Python Objects (Instances)
  • Adding attributes to Class
    • Instance Attributes
    • Class Attributes
  • Instantiaiting Objects
    • Review Exercises (#1)
  • Instance Methods
    • Modifying Attributes
    • Defining Methods within a Class
  • Python Object Inheritance
    • Parent vs Child Classes
    • Overriding the functionality of a Parent Class
  • Conclusion
    • Review Exercises (#2)

OOP: Introduction

  • Means of structuring programs so that properties and behaviours are bundled into individual objects
  • An object could represent a Person with:
    • properties like name, address, age
    • behaviours like walking, talking, running
  • Models real-world entities as software objects, which have some data associated with them and can perform certain functions
  • Development is faster and cheaper, with better software maintainability
    • Higher-quality software, which is also extensible with new methods and attributes
  • The learning curve is, however, steeper
    • The concept may be too complex for beginners

OOP Example

  • Example of a class is the class Dog
    • Don't think of it as a specific dog/own dog
  • Dogs usually have a name and age : instance attributes/properties
  • Dogs can bark: methods/behaviours
  • Specific dog/own dog Ozzy belongs to the class Dog
    • Attributes: name == "Ozzy" , age == 2

Classes in Python

  • A class is a mechanism used to create new user-defined data structures. It contains data as well as the methods used to process that data
  • Class just provides structure — it’s a blueprint for how something should be defined, but it doesn’t actually provide any real content itself
  • The Dog() class may specify that the name and age are necessary for defining a dog, but it will not actually state what a specific dog’s name or age is.
  • think of a class as an idea for how something should be defined

Define a Class in Python

  • Use the class keyword, followed by the class name and a colon
In [1]:
class Dog:
    pass

Python Objects (Instances)

  • While the class is the blueprint, an instance is a copy of the class with actual values, literally an object belonging to a specific class
  • It’s not an idea anymore; it’s an actual animal,
    • like a dog named Roger who’s eight years old
  • Before you can create individual instances of an object, we must first specify what is needed by defining a class.

Instance Attributes

  • All classes create objects, and all objects contain characteristics called attributes/properties
  • Use the __init__ method - initializer to instantiate objects
    • used to initialize an object’s initial attributes by giving them their default value (or state)
    • This method takes one argument self, which refers to the object itself (e.g., Dog)
  • self in Python is equivalent to this in C++ or Java

Instantiating Objects

  • To instantiate an object, type the class name, followed by ()
  • Assign this to a variable to keep track of the object
In [2]:
class Dog:
    
    # Initializer
    def __init__(self):
        pass
    
# Instantiating object    
ozzy = Dog()
print(ozzy)
<__main__.Dog object at 0x000001DC2AE8F1D0>

Adding Attributes to the Class

  • After printing ozzy, it is clear that this object is a dog.
  • Let's give the Dog class attributes : a name and age, by rewriting it:
In [3]:
class Dog:

    # Initializer / Instance Attributes
    def __init__(self, nm, ag):
        self.name = nm
        self.age = ag

Class Attributes

  • While instance attributes are specific to each object, class attributes are the same for all instances — which in this case is all dogs
In [4]:
class Dog:

    # Class Attribute
    species = 'mammal'

    # Initializer / Instance Attributes
    def __init__(self, name, age):
        self.name = name
        self.age = age

Complete Example in Python with class, attributes and objects

In [5]:
class Dog:

    # Class Attribute
    species = 'mammal'

    # Initializer / Instance Attributes
    def __init__(self, nm, ag):
        self.name = nm
        self.age = ag

# Instantiate the Dog object
ozzy = Dog("Ozzy", 5)
skippy = Dog("Skippy", 6)

# Access the instance attributes
print(ozzy.name, ozzy.age)
print(skippy.name, skippy.age)

print(ozzy.name + " is " + str(ozzy.age) + " year(s) old!")

# Access the class attributes
print(Dog.species)
print(ozzy.species)
print(skippy.species)

# Is Ozzy a mammal?
if ozzy.species == "mammal":
    print(ozzy.name, ozzy.species)
Ozzy 5
Skippy 6
Ozzy is 5 year(s) old!
mammal
mammal
mammal
Ozzy mammal

Instance Methods

  • Instance methods are defined inside a class and are used to get the contents of an instance
  • They can also be used to perform operations with the attributes of our objects
  • Like the init method, the first argument is always self
In [6]:
class Dog:

    # Class Attribute
    species = 'mammal'

    # Initializer / Instance Attributes
    def __init__(self, nm, ag):
        self.name = nm
        self.age = ag

    # instance method
    def doginfo(self):
        print(self.name + " is " + str(self.age) + " year(s) old.")

    # instance method
    def speak(self, sound):
        return (self.name, sound)

# Instantiate the Dog object
mikey = Dog("Mikey", 6)
ozzy = Dog("Ozzy", 2)
skippy = Dog("Skippy", 12)
filou = Dog("Filou", 8)

# call our instance methods
mikey.doginfo()
print(mikey.speak("Gruff Gruff"))

ozzy.doginfo()
print(ozzy.speak("Bark Bark"))

skippy.doginfo()
filou.doginfo()
Mikey is 6 year(s) old.
('Mikey', 'Gruff Gruff')
Ozzy is 2 year(s) old.
('Ozzy', 'Bark Bark')
Skippy is 12 year(s) old.
Filou is 8 year(s) old.

Review Exercise #1

  • Using the same Dog class, instantiate three new dogs, each with a different age. Then write a function called, get_biggest_number(), that takes number of ages as arguments and returns the oldest one.
  • Then output the age of the oldest dog like so:
    • The oldest dog is 7 years old.

Python Object Inheritance

  • Inheritance is the process by which one class takes on the attributes and methods of another
  • Newly formed classes are called child classes, and the classes that child classes are derived from are called parent classes
  • Child classes override or extend the functionality (e.g., attributes and behaviors) of parent classes
  • In other words, child classes inherit all of the parent’s attributes and behaviors but can also specify different behavior to follow

Extending the Functionality of a Parent Class

In [7]:
# Parent class
class Dog:

    # Class attribute
    species = 'mammal'

    # Initializer / Instance attributes
    def __init__(self, nm, ag):
        self.name = nm
        self.age = ag

    # instance method
    def description(self):
        print(self.name + " is " + str(self.age) + " year(s) old!")

    # instance method
    def speak(self, sound):
        print(self.name + " says " + sound)


# Child class (inherits from Dog class)
class RussellTerrier(Dog):
    def run(self, speed):
        print(self.name + " runs " + speed)


# Child class (inherits from Dog class)
class Bulldog(Dog):
    def run(self, speed):
        print(self.name + " runs " + speed)


# Child classes inherit attributes and
# behaviors from the parent class
jim = Bulldog("Jim", 12)
jim.description()
jim.speak("Bark Bark!")

skippy = RussellTerrier("Skippy", 8)
skippy.description()

# Child classes have specific attributes
# and behaviors as well
jim.run("slowly")
skippy.run("fast")
Jim is 12 year(s) old!
Jim says Bark Bark!
Skippy is 8 year(s) old!
Jim runs slowly
Skippy runs fast

Parent vs. Child Classes

  • The isinstance() function is used to determine if an instance is also an instance of a certain parent class
In [8]:
# Parent class
class Dog:

    # Class attribute
    species = 'mammal'

    # Initializer / Instance attributes
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # instance method
    def description(self):
        print(self.name + " is " + str(self.age) + " year(s) old!")

    # instance method
    def speak(self, sound):
        print(self.name + " says " + sound)


# Child class (inherits from Dog() class)
class RussellTerrier(Dog):
    def run(self, speed):
        print(self.name + " runs " + speed)


# Child class (inherits from Dog() class)
class Bulldog(Dog):
    def run(self, speed):
        print(self.name + " runs " + speed)


# Child classes inherit attributes and
# behaviors from the parent class
jim = Bulldog("Jim", 12)
jim.description()

# Child classes have specific attributes
# and behaviors as well
jim.run("slowly")

# Is jim an instance of Dog()?
print(isinstance(jim, Dog))

# Is julie an instance of Dog()?
julie = Dog("Julie", 100)
print(isinstance(julie, Dog))

# Is johnny walker an instance of Bulldog()
johnnywalker = RussellTerrier("Johnny Walker", 4)
print(isinstance(johnnywalker, Bulldog))

# Is julie and instance of jim?
print(isinstance(julie, jim))
Jim is 12 year(s) old!
Jim runs slowly
True
True
False
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-df9ce49686ec> in <module>()
     52 
     53 # Is julie and instance of jim?
---> 54 print(isinstance(julie, jim))

TypeError: isinstance() arg 2 must be a type or tuple of types

Why?

  • Both jim and julie are instances of the Dog() class, while johnnywalker is not an instance of the Bulldog() class
  • We tested if julie is an instance of jim, which is impossible since jim is an instance of a class rather than a class itself—hence the reason for the TypeError

Overriding the Functionality of a Parent Class

  • child classes can also override attributes and behaviors from the parent class
In [9]:
# Parent class
class Dog:
    
    # Class Attribute
    species = 'mammal'

# Child class (inherits from Dog class)    
class SomeBreed(Dog):
    pass

# Child class (inherits from Dog class)
class SomeOtherBreed(Dog):
    species = 'reptile'

frank = SomeBreed()
print(frank.species)

beans = SomeOtherBreed()
print(beans.species)
mammal
reptile

Why?

  • The SomeBreed() class inherits the species from the parent class, while the SomeOtherBreed() class overrides the species, setting it to reptile

Review Exercise #2

  • What’s a class?
  • What’s an instance?
  • What’s the relationship between a class and an instance?
  • What’s the Python syntax used for defining a new class?
  • What’s the spelling convention for a class name?
  • How do you instantiate, or create an instance of, a class?
  • How do you access the attributes and behaviors of a class instance?
  • What’s a method?
  • What’s the purpose of self?
  • What’s the purpose of the init method?
  • Describe how inheritance helps prevent code duplication.
  • Can child classes override properties of their parents?

Additional Resources: