Python Basics - 08. Object-Oriented Programming (OOP)

Python is an object-oriented language. OOP allows developers to bundle properties (data) and behaviors (methods) into individual entities called Objects. This notebook explains how to define and use objects and their relationships.

Download Notebook

Download this notebook

1. Defining Classes and Creating Objects

  • class: The keyword to define a new class (a blueprint for creating objects).

  • __init__: The “constructor” or initialization method. It sets up the starting state of the object properties.

  • self: Refers to the specific instance of the object being operated on.

class Dog:
    # Class Attribute (shared by every Dog instance)
    species = "Canis familiaris"

    def __init__(self, name, age):
        # Instance Attributes (unique to each Dog instance)
        self.name = name
        self.age = age

    # An instance Method
    def description(self):
        return f"{self.name} is {self.age} years old."

    def speak(self, sound):
        return f"{self.name} says '{sound}'!"

# Instantiating completely separate objects from the 'Dog' blueprint
buddy = Dog("Buddy", 9)
miles = Dog("Miles", 4)

print(f"Species: {buddy.species}")
print(buddy.description())
print(miles.speak("Woof woof"))
Species: Canis familiaris
Buddy is 9 years old.
Miles says 'Woof woof'!

2. Inheritance

Inheritance allows a new class (Child Class) to adopt the methods and attributes of another class (Parent Class), promoting code reuse.

# GoldenRetriever inherits from the Parent 'Dog'
class GoldenRetriever(Dog):
    
    # We can override the speak method specifically for this breed
    def speak(self, sound="Bark"):
        # 'super()' lets us call methods defined in the parent class
        return super().speak(sound)

goldie = GoldenRetriever("Goldie", 5)

# Still has access to description() defined in Dog
print(goldie.description())

# Using the overridden parent class logic
print(goldie.speak())      # Uses the default "Bark"
print(goldie.speak("Arf")) # We can still provide a custom sound
Goldie is 5 years old.
Goldie says 'Bark'!
Goldie says 'Arf'!

3. Magic Methods and Polymorphism

Magic methods (also called dunder methods) let your objects integrate with Python syntax. Polymorphism means different classes can provide the same method name with class-specific behavior.

class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    # __repr__ controls the object's developer-friendly print format.
    def __repr__(self):
        return f"Vector2D(x={self.x}, y={self.y})"

    # __add__ enables using + between two Vector2D instances.
    def __add__(self, other):
        return Vector2D(self.x + other.x, self.y + other.y)

v1 = Vector2D(1, 2)
v2 = Vector2D(3, 4)
print(v1 + v2)

# Polymorphism demo:
# different classes share the same method name with different behavior.
class Cat:
    def speak(self):
        return "Meow"

class Bird:
    def speak(self):
        return "Tweet"

def animal_sound(animal):
    print(animal.speak())

animal_sound(Cat())
animal_sound(Bird())
Vector2D(x=4, y=6)
Meow
Tweet

4. Superclass (Base Class) and super()

A Superclass (also called a base class) provides shared attributes and behavior. A Subclass extends or customizes that behavior.

super() lets a subclass call methods from its superclass without hardcoding the class name. This makes inheritance code cleaner and easier to maintain.

class Animal:
    """Superclass: defines behavior common to all animals."""

    def __init__(self, name):
        self.name = name

    def speak(self):
        return f"{self.name} makes a sound"


class Dog(Animal):
    """Subclass of Animal: extends and overrides behavior."""

    def __init__(self, name, breed):
        # Use super() to reuse superclass initialization logic.
        super().__init__(name)
        self.breed = breed

    def speak(self):
        # Optional: call superclass behavior first, then customize.
        base = super().speak()
        return f"{base}; {self.name} barks"


d = Dog("Buddy", "Golden Retriever")
print(d.name)
print(d.breed)
print(d.speak())
Buddy
Golden Retriever
Buddy makes a sound; Buddy barks