Python Inheritance
$count++; if($count == 1) { include "../mobilemenu.php"; } ?> if ($count == 2) { include "../sharemediasubfolder.php"; } ?>
Inheritance is an OOP concept that enables creating new classes from existing ones, allowing code reuse and flexibility in design. In Python, inheritance allows a class (called the child or subclass) to inherit properties and methods from another class (called the parent or superclass). This allows specialized behavior while leveraging the functionality of existing classes.
1. Basics of Inheritance
In basic inheritance, the child class inherits all attributes and methods from the parent class. If no additional behavior is needed, we can use the parent’s functionality directly in the child class.Basic Inheritance Syntax:
# Defining a parent class
class Animal:
def __init__(self, species):
self.species = species
def make_sound(self):
return "Some generic animal sound"
# Child class inheriting from Animal
class Dog(Animal):
pass # Inherits all properties and methods from Animal
# Creating an object of the child class
dog = Dog("Canine")
print(dog.species) # Inherited attribute
print(dog.make_sound()) # Inherited method
Output:
Canine
Some generic animal sound
2. Overriding Methods in the Child Class
Overriding allows a child class to provide a specific implementation for a method that already exists in the parent class. This is useful for adding customized behavior.class Animal:
def __init__(self, species):
self.species = species
def make_sound(self):
return "Some generic animal sound"
# Child class with overridden method
class Dog(Animal):
def make_sound(self): # Override parent method
return "Woof!"
dog = Dog("Canine")
print(dog.make_sound()) # Calls overridden method
Output:
Woof!
3. Using the `super()` Function
The `super()` function allows a child class to access methods or attributes of its parent class. This is particularly useful when overriding methods and you still need some behavior from the parent class.class Animal:
def __init__(self, species):
self.species = species
def make_sound(self):
return "Some generic animal sound"
class Dog(Animal):
def __init__(self, species, name):
super().__init__(species) # Call parent constructor
self.name = name
def make_sound(self):
sound = super().make_sound() # Call parent method
return f"{sound}... But {self.name} barks 'Woof!'"
dog = Dog("Canine", "Buddy")
print(dog.make_sound())
Output:
Some generic animal sound... But Buddy barks 'Woof!'
4. Multiple Inheritance
Python supports multiple inheritance, where a class can inherit from more than one parent class. This can create complex relationships but can also introduce complexity and ambiguity, especially when both parents have methods with the same name.Example of Multiple Inheritance:
class Flyer:
def fly(self):
return "I can fly!"
class Swimmer:
def swim(self):
return "I can swim!"
# Amphibian class inherits from both Flyer and Swimmer
class Duck(Flyer, Swimmer):
pass
duck = Duck()
print(duck.fly())
print(duck.swim())
Output:
I can fly!
I can swim!
5. The Method Resolution Order (MRO)
In cases of multiple inheritance, Python determines the order in which methods are resolved using the Method Resolution Order (MRO). The MRO defines the sequence in which the parent classes are searched when looking for a method.Example with MRO:
class A:
def method(self):
return "Method in A"
class B(A):
def method(self):
return "Method in B"
class C(A):
def method(self):
return "Method in C"
class D(B, C):
pass
d = D()
print(d.method()) # Checks MRO to resolve which method to call
print(D.__mro__) # Displays MRO
Output:
Method in B
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
6. Inheritance with Property Overriding and Validation
Properties in Python allow us to add getter, setter, and deleter methods. By using inheritance, subclasses can override property methods to introduce specific validations.class Product:
def __init__(self, name, price):
self._name = name
self._price = price
@property
def price(self):
return self._price
@price.setter
def price(self, value):
if value < 0:
raise ValueError("Price cannot be negative")
self._price = value
# Subclass that overrides price validation
class DiscountedProduct(Product):
@Product.price.setter
def price(self, value):
if value < 5:
raise ValueError("Discounted price cannot be below $5")
self._price = value
product = Product("Gadget", 50)
product.price = 30
print("Regular Product Price:", product.price)
discounted_product = DiscountedProduct("Gadget", 10)
discounted_product.price = 6
print("Discounted Product Price:", discounted_product.price)
Output:
Regular Product Price: 30
Discounted Product Price: 6
7. Advanced: Inheriting from Built-in Classes
In Python, we can also inherit from built-in classes like `list`, `dict`, etc. This is useful for extending built-in functionality.Example of Extending a Built-in Class:
class CustomList(list):
def sum(self):
return sum(self)
custom_list = CustomList([1, 2, 3, 4])
print("Sum of elements:", custom_list.sum())
Output:
Sum of elements: 10
8. Composition vs. Inheritance
While inheritance is a powerful tool, there are cases where composition (using classes as attributes rather than parents) is more appropriate, especially when the "is-a" relationship doesn’t fit.Example of Composition:
class Engine:
def start(self):
return "Engine started"
class Car:
def __init__(self):
self.engine = Engine() # Composition
def start(self):
return self.engine.start()
car = Car()
print(car.start())
Output:
Engine started
Summary
Inheritance in Python provides a robust way to create hierarchical relationships between classes, facilitating code reuse and logical design. Key concepts include method overriding, `super()`, multiple inheritance, MRO, and extending built-in classes.