Python Inheritance

Inheritance in Python is basically an object-oriented programming method where a class, termed the child or derived class, inherits the properties and methods of another class known as the parent or base class. This facilitates code reusability and makes programs more understandable and maintainable.

How Inheritance Works

  1. Parent Class (Base Class)
    This is the class whose attributes and methods are inherited by the child class.
  2. Child Class (Derived Class)
    This is the class that has inheritance from the parent class. It can use all the attributes and methods of the parent class and can also define its own.

Syntax of Inheritance

class ParentClass:
    # parent class code

class ChildClass(ParentClass):
    # child class code

Types of Inheritance in Python

1. Single Inheritance

The child class inherits from only one parent class.

class Animal:
    def speak(self):
        print("Animal speaks")

class Dog(Animal):
    def bark(self):
        print("Dog barks")

# Example Usage
d = Dog()
d.speak()  # Inherited from Animal
d.bark()   # Defined in Dog

2. Multiple Inheritance

The child class inherits from more than one parent class.

class A:
    def method_a(self):
        print("Method A")

class B:
    def method_b(self):
        print("Method B")

class C(A, B):  # Inherits from both A and B
    def method_c(self):
        print("Method C")

# Example Usage
c = C()
c.method_a()
c.method_b()
c.method_c()

3. Multilevel Inheritance

A class inherits from a parent class, and another class inherits from that child class.

class Animal:
    def speak(self):
        print("Animal speaks")

class Mammal(Animal):
    def walk(self):
        print("Mammal walks")

class Dog(Mammal):
    def bark(self):
        print("Dog barks")

# Example Usage
d = Dog()
d.speak()  # From Animal
d.walk()   # From Mammal
d.bark()   # From Dog

4. Hierarchical Inheritance

Multiple child classes inherit from the same parent class.

class Animal:
    def speak(self):
        print("Animal speaks")

class Dog(Animal):
    def bark(self):
        print("Dog barks")

class Cat(Animal):
    def meow(self):
        print("Cat meows")

# Example Usage
dog = Dog()
cat = Cat()
dog.speak()
dog.bark()
cat.speak()
cat.meow()

5. Hybrid Inheritance

This is a combination of two or more types of inheritance.

Key Features of Inheritance

  1. Access Parent Class Members
    The child class can access the public members of the parent class directly.

2. Method Overriding
The child class can override a method from the parent class to give a particular implementation.

class Parent:
    def show(self):
        print("Parent show method")

class Child(Parent):
    def show(self):  # Overriding the parent class method
        print("Child show method")

c = Child()
c.show()  # Outputs: "Child show method"

3. super() Keyword
The super() function is used to call a method from the parent class inside the child class.

class Parent:
    def show(self):
        print("Parent method")

class Child(Parent):
    def show(self):
        super().show()  # Calling the parent class method
        print("Child method")

c = Child()
c.show()

4. isinstance() and issubclass() Functions

  • issubclass(child, parent): Checks if a class is a subclass of another.
  • isinstance(object, class): Checks if an object is an instance of a class or its subclass.
class Animal:
    pass

class Dog(Animal):
    pass

d = Dog()
print(isinstance(d, Dog))      # True
print(isinstance(d, Animal))  # True
print(issubclass(Dog, Animal))# True

Advantages of Inheritance

  1. Code Reusability: Share common functionality between classes.
  2. Extensibility: Build on existing code without modifying it.
  3. Modularity: Organize code into logical hierarchies.

Important Notes

  1. Private Members are Not Inherited
    Private members (attributes prefixed with __) are not accessible in the child class.
class Parent:
    def __init__(self):
        self.__private = "Private"

class Child(Parent):
    pass

c = Child()
print(c.__private)  # Error: AttributeError

2. Avoid Diamond Problem with super()
In cases of multiple inheritance, Python resolves method calls using the MRO (Method Resolution Order), which avoids the “diamond problem.”

class A:
    def show(self):
        print("A")

class B(A):
    def show(self):
        print("B")

class C(A):
    def show(self):
        print("C")

class D(B, C):
    pass

d = D()
d.show()  # Outputs: B (MRO decides)