Inheritance and super()
Inheritance allows a class (child) to inherit attributes and methods from another class (parent). This lets you build on existing functionality without rewriting code.
The child class can add new attributes and methods, or override inherited ones. Use super() to call the parent class's methods from within the child class.
Example
# Parent class
class Animal:
def __init__(self, name, species):
self.name = name
self.species = species
def speak(self):
return f"{self.name} makes a sound."
def __str__(self):
return f"{self.name} ({self.species})"
# Child class — inherits from Animal
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name, species="Dog") # Call parent constructor
self.breed = breed # New attribute
# Override parent method
def speak(self):
return f"{self.name} says: Woof!"
class Cat(Animal):
def __init__(self, name, indoor=True):
super().__init__(name, species="Cat")
self.indoor = indoor
def speak(self):
return f"{self.name} says: Meow!"
# Using inheritance
dog = Dog("Buddy", "Labrador")
cat = Cat("Whiskers")
print(dog) # Buddy (Dog)
print(dog.speak()) # Buddy says: Woof!
print(dog.breed) # Labrador
print(cat.speak()) # Whiskers says: Meow!
print(isinstance(dog, Animal)) # True - class Child(Parent): — define a class that inherits from Parent
- super().__init__() — call the parent's constructor
- super().method() — call a parent's method from the child
- isinstance(obj, Class) — check if an object is an instance of a class
- issubclass(Child, Parent) — check if a class inherits from another
Try Inheritance
JavaScript
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return f"{self.name} makes a sound."
class Dog(Animal):
def speak(self):
return f"{self.name} says: Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says: Meow!"
dog = Dog("Buddy")
cat = Cat("Whiskers")
print(dog.speak())
print(cat.speak())
print(f"Is Dog an Animal? {isinstance(dog, Animal)}") Notes
- Python supports multiple inheritance (inheriting from multiple parents), but use it carefully. The Method Resolution Order (MRO) determines which parent method is called first.
Polymorphism
Polymorphism means 'many forms.' It allows different classes to be treated through the same interface. When you call a method on an object, Python calls the correct version based on the object's actual class.
This is powerful because you can write code that works with objects of different types without knowing their specific class — as long as they share the same method names.
Example
class Shape:
def area(self):
raise NotImplementedError("Subclasses must implement area()")
def describe(self):
return f"{self.__class__.__name__}: area = {self.area():.2f}"
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14159 * self.radius ** 2
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class Triangle(Shape):
def __init__(self, base, height):
self.base = base
self.height = height
def area(self):
return 0.5 * self.base * self.height
# Polymorphism in action — same interface, different behavior
shapes = [Circle(5), Rectangle(4, 6), Triangle(3, 8)]
for shape in shapes:
print(shape.describe())
# Circle: area = 78.54
# Rectangle: area = 24.00
# Triangle: area = 12.00 Try Polymorphism
JavaScript
class Circle:
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14159 * self.radius ** 2
class Rectangle:
def __init__(self, w, h):
self.w = w
self.h = h
def area(self):
return self.w * self.h
shapes = [Circle(5), Rectangle(4, 6), Circle(3)]
for shape in shapes:
print(f"{type(shape).__name__}: {shape.area():.2f}") Notes
- Python uses 'duck typing' — if an object has the right methods, it can be used in place of another type. 'If it walks like a duck and quacks like a duck, it's a duck.'
