Today we are going to revisit Classes, and introduce a concept called inheritance. Let’s motivate the concept with following:

class Animal:
def __init__(self, weight, height):
self.height = height
self.weight = weight


This is a pretty generic Animal class initialized with attributes of weight and height. Suppose now we want to create a Fish class. Fish are animals, but they also have the specific ability to swim:

class Fish:
def __init__(self, weight, height):
self.height = height
self.weight = weight

def swim(self):
print("Fish is swimming!")


That __init__ method looks exactly the same between both classes! And they should, given that fish are animals. However, what happens if you change the __init__ method for Animal? Then you would have to change it in both places. It would be nicer if we only had to change it in one place. This is where inheritance comes in:

class Fish(Animal):
def swim(self):
print("Fish is swimming!")


Wow! That looks a lot simpler! We completely removed the __init__ method, and instead, placed the Animal class name in parentheses next to Fish. Let’s see what happens when we do that:

f = Fish(5, 6)
print(f.height)
f.swim()


This will output:

5
Fish is swimming!


By placing the Animal class in parenthesis next to Fish, we equipped the Fish class with all of the methods and attributes that come with the Animal class. That’s why f.height works (otherwise, we would have raised an AttributeError since the attribute would not have existed for Fish instances). In other words, the Fish class inherits everything an Animal has.

However, just because attributes and methods are inherited, does not mean they cannot be changed. You can override anything that is inherited and make it specific to the subclass (i.e. the class that is inheriting):

class BigFish(Fish):
def swim(self):
print("Fish is swimming...slowly")

f = BigFish(5, 6)
print(f.height)
f.swim()


This will output:

5
Fish is swimming...slowly


The BigFish class inherits everything from the Fish class, which in turn, inherits everything from the Animal class. That is why BigFish has a height. BigFish also inherits the swim method from Fish, but because we define our own swim method, it overrides the one from Fish, giving us the output of "Fish is swimming...slowly" instead of "Fish is swimming!".

Inheritance is a powerful concept that allows us to create hierarchies of classes (e.g. AnimalFishBigFish) without duplicating everything that these classes should share with each other (i.e. methods and attributes).

Let’s stop here and answer questions to review what we learned:

• Create a Toy class with attributes weight and price. Then create a Train class that inherits from Toy. Add a method to Toy that prints: "I go choo-choo!" (solution).

• Create a RareTrain class that inherits from Train. Override the method you defined for Train to print: "I am a rare train that goes choo-choo!" (solution).

Inheritance is relatively heavy topic, but once understood, can help you to write more powerful, effective code. Once you do, feel free to move to the next lesson!