🔄 Quick Recap (Day 11)

  • You defined classes, created objects with attributes, and called methods.

  • You saw how __init__ and self work inside a class.

🎯 What You’ll Learn Today

  1. What inheritance is and how to create subclasses.

  2. How to use super() to call parent class methods.

  3. What polymorphism means in Python.

  4. How to override methods for custom behavior.

📖 Overview: Inheritance

Inheritance lets a new class (child) reuse attributes and methods of an existing class (parent). It’s like a specialized recipe that builds on a base recipe.

class Vehicle:
    def __init__(self, make, model):
        self.make = make
        self.model = model

    def drive(self):
        print(f"Driving a {self.make} {self.model}...")

# Car inherits from Vehicle
class Car(Vehicle):
    def __init__(self, make, model, doors):
        super().__init__(make, model)  # call parent __init__
        self.doors = doors  # new attribute

    def drive(self):  # override drive method
        print(f"Driving a {self.doors}-door {self.make} {self.model}!")
  • class Car(Vehicle): declares that Car inherits from Vehicle.

  • super().__init__() calls the parent class’s constructor.

  • Overriding drive() changes behavior for Car objects.

📖 Overview: Polymorphism

Polymorphism means “many forms.” Different classes can define the same method name, and you can call it without knowing the exact class type.

class Bike(Vehicle):
    def drive(self):
        print(f"Riding a {self.make} {self.model} bike!")

# Both Car and Bike share drive() interface
vehicles = [Car("Toyota", "Corolla", 4), Bike("Giant", "Escape 3")]
for v in vehicles:
    v.drive()

Output:

Driving a 4-door Toyota Corolla!
Riding a Giant Escape 3 bike!

🧙‍♂️ Take the Wand and Try Yourself

  1. Create a file named shapes.py.

  2. Define a parent class Shape with a method area() that raises NotImplementedError.

  3. Create subclasses Square and Circle:

    • Square takes side attribute; its area() returns side * side.

    • Circle takes radius attribute; its area() returns 3.14 * radius * radius.

  4. Instantiate one Square and one Circle, then:

    • Print each shape’s class name and area in a loop.

Solution Example (shapes.py):

# shapes.py
class Shape:
    def area(self):
        raise NotImplementedError("Subclasses must implement area()")

class Square(Shape):
    def __init__(self, side):
        self.side = side

    def area(self):
        return self.side * self.side

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14 * self.radius * self.radius

# Create instances
shapes = [Square(4), Circle(3)]
for shape in shapes:
    print(f"{shape.__class__.__name__} area:", shape.area())

Expected output:

Square area: 16
Circle area: 28.26

Run:

python shapes.py

Once the output matches, you’ve mastered inheritance and polymorphism!

Up next: Day 13: Magic Methods & Operator Overloading

Keep Reading