super() and Method Overriding
Inheritance gives you the parent's behaviour for free. Sometimes you want to change it for the subclass, or build on top of it. That is what overriding and super() are for.
Inheritance gives you the parent's behaviour for free. Sometimes the subclass needs to do things differently, or do a bit extra. That is what overriding solves.
Define a method with the same name in the subclass and Python uses the subclass version:
The parent class is not changed. Other subclasses or instances of Animal still see the original method.
What will be the output?
When a subclass defines its own __init__, the parent's setup does not run automatically. Use super() to call it.
super().__init__(name) runs the parent's __init__, so self.name gets set:
What will be the output?
Without super(), the parent setup is skipped and you lose those attributes.
Forgetting super().__init__() means self.name never gets set:
super() works for any method, not just __init__. Use it when you want to extend a method instead of replacing it.
The subclass calls the parent's describe and adds extra detail:
What will be the output?
What will be the output?
What will be the output?
What will be the output?
What will be the output?