Inheritance
Inheritance lets a class (child/subclass) inherit attributes and methods from another class (parent/superclass). Use it when there's a genuine "is-a" relationship between objects.
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
raise NotImplementedError("Subclasses must implement speak()")
def describe(self):
return f"{self.name} is {self.age} years old"
def __repr__(self):
return f"{type(self).__name__}(name={self.name!r})"
class Dog(Animal): # Dog inherits from Animal
def __init__(self, name, age, breed):
super().__init__(name, age) # Call parent __init__
self.breed = breed
def speak(self): # Override parent method
return f"{self.name}: Woof!"
def fetch(self, item):
return f"{self.name} fetches the {item}!"
class Cat(Animal):
def speak(self):
return f"{self.name}: Meow!"
def purr(self):
return f"{self.name} purrs..."
rex = Dog("Rex", 3, "Labrador")
whiskers = Cat("Whiskers", 5)
print(rex.speak()) # Rex: Woof!
print(whiskers.speak()) # Whiskers: Meow!
print(rex.describe()) # Rex is 3 years old (inherited!)
print(rex.fetch("ball")) # Rex fetches the ball!isinstance() and issubclass()
isinstance(rex, Dog) # True
isinstance(rex, Animal) # True โ Dog IS an Animal
isinstance(rex, Cat) # False
issubclass(Dog, Animal) # True
issubclass(Dog, Cat) # False
issubclass(Dog, object) # True โ everything inherits from object
type(rex) == Dog # True
type(rex) == Animal # False โ type() is strictPolymorphism
Polymorphism means the same operation works on different types. Python uses "duck typing" โ if it looks like a duck and quacks, it's a duck.
animals = [Dog("Rex", 3, "Lab"), Cat("Whiskers", 5), Dog("Buddy", 2, "Beagle")]
# Polymorphic: same method call, different behavior
for animal in animals:
print(animal.speak())
# Rex: Woof!
# Whiskers: Meow!
# Buddy: Woof!
# Works because all have speak() โ no inheritance required!
class Robot:
def speak(self):
return "Beep boop"
things = [Dog("Rex", 3, "Lab"), Robot()]
for thing in things:
print(thing.speak()) # Works! Both have speak()Abstract Base Classes
from abc import ABC, abstractmethod
class Shape(ABC): # Abstract base class โ cannot be instantiated
@abstractmethod
def area(self) -> float:
pass
@abstractmethod
def perimeter(self) -> float:
pass
def describe(self): # Concrete method โ inherited as-is
return f"{type(self).__name__}: area={self.area():.2f}, perimeter={self.perimeter():.2f}"
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
import math
return math.pi * self.radius ** 2
def perimeter(self):
import math
return 2 * math.pi * self.radius
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
shapes = [Circle(5), Rectangle(4, 6)]
for s in shapes:
print(s.describe())
# Circle: area=78.54, perimeter=31.42
# Rectangle: area=24.00, perimeter=20.00Multiple Inheritance and MRO
class Flyable:
def fly(self):
return f"{self.name} is flying"
class Swimmable:
def swim(self):
return f"{self.name} is swimming"
class Duck(Animal, Flyable, Swimmable):
def speak(self):
return f"{self.name}: Quack!"
donald = Duck("Donald", 3)
print(donald.fly()) # Donald is flying
print(donald.swim()) # Donald is swimming
print(donald.speak()) # Donald: Quack!
# Method Resolution Order (MRO) โ which class wins?
print(Duck.__mro__)
# [Duck, Animal, Flyable, Swimmable, object]Key Takeaways
- Inheritance for "is-a" relationships: Dog is an Animal
- super() calls parent class: always pass through args to super().__init__
- Override methods selectively: only what changes in the subclass
- Duck typing over inheritance: if it has the method, it works
- Abstract classes enforce interfaces: subclasses MUST implement abstract methods
Practice Exercises
- Create an
Employeehierarchy: baseEmployeeclass, thenManager(has a team list) andDeveloper(has a list of skills). Add apay()method that's overridden in subclasses. - Create an abstract
Vehicleclass with abstractfuel_type()andrange_km(). ImplementCar,ElectricCar, andBicycle. - Write a function that takes a list of Shapes and returns total area. It should work with any Shape subclass.