With inheritance, a new class (the child) starts with everything from an existing class (the parent). The child can then add new methods or replace, or override, the ones it inherited.
The program
python
class Animal: def __init__(self, name): self.name = name def speak(self): return f"{self.name} makes a sound" def describe(self): return f"{self.name} is a {type(self).__name__.lower()}" class Cat(Animal): def speak(self): return f"{self.name} says: Meow!" class Dog(Animal): def __init__(self, name, tricks): super().__init__(name) self.tricks = tricks def speak(self): return f"{self.name} says: Woof! (knows {len(self.tricks)} tricks)" class Fish(Animal): pass for animal in [Cat("Whiskers"), Dog("Rex", ["sit", "stay"]), Fish("Nemo")]: print(animal.speak(), "|", animal.describe())
output
Whiskers says: Meow! | Whiskers is a cat Rex says: Woof! (knows 2 tricks) | Rex is a dog Nemo makes a sound | Nemo is a fish
How it works
class Cat(Animal)means "Cat inherits from Animal". Cat gets__init__,speakanddescribewithout writing them again.- Cat and Dog define their own
speak, which overrides the parent's. Fish defines nothing, so it uses Animal'sspeak. - Dog needs an extra attribute, so it has its own
__init__.super().__init__(name)runs Animal's__init__first, which setsself.name. Without that line, a Dog would have noname. - The loop calls
speak()on each animal without checking its type. Each object runs its own version. This is called polymorphism.
Checking the family
isinstance() is True for the object's class and for every parent class above it:
python
class Animal: pass class Dog(Animal): pass rex = Dog() print(isinstance(rex, Dog)) print(isinstance(rex, Animal)) print(issubclass(Dog, Animal)) print(isinstance(Animal(), Dog))
output
True True True False