This is an article on Python Subclasses and inheritance. Before reading on, if you haven’t done so already, I strongly recommend you check out my write up on Python Classes.
Let’s get cracking!
A Python Sub-what?
Let’s say you have a class already set up. In my previous article on classes, I created a “single tier” Person class. That is, you use the Person
class to create a person object. That’s it. (I created Bob using this class).
What if I need more depth though? Let’s use vehicles as an example. Keeping it simple, here’s how you might look at the tiers or levels of a Vehicle:
Vehicle > Car > Mercedes.
See how we have multiple levels?
Vehicle
would be the parent class-
Car
would be the Subclass Mercedes
would be an object we create using theCar
subclass.
Not only that, but the Mercedes we just created will inherit all of the attributes and functions associated with the Vehicle
parent class and those from the Car
class. There’s a cascading effect in play here.
A way of looking at this, being an object of the Car
class, the Mercedes:
- Has four wheels
- Has a windshield
- Does not have two wheels
As you expand an app using this example, you’d also define subclasses of the parent Vehicle
class for motorbikes, bicycles, trucks, trains, buses, planes, etc, each of which would have their own unique attributes.
A Familiar Example
Full code here.
To demonstrate this in code, I wrote up a Boss
class. We’ve all likely experienced what it’s like to have a “good” and a “bad” boss at work, so go with me on this.
Imagine you’re designing a game that has a “Boss” in it. I can imagine myself coding up a Boss class then use this class to create different types of Bosses:
class Boss(object):
def __init__(self, name, attitude, behaviour, face):
self.name = name
self.attitude = attitude
self.behaviour = behaviour
self.face = face
def get_attitude(self):
return self.attitude
def get_behaviour(self):
return self.behaviour
def get_face(self):
return self.face
A full explanation of a class written like this is found in my Python Classes article.
A boss would have a name
, an attitude
, a behaviour
and a face
(facial expression!).
Now, let’s start working on the Boss Subclasses. What kind of Bosses do we want to be able to make? How about a GoodBoss
and a BadBoss
?
class GoodBoss(Boss):
def __init__(self,
name,
attitude,
behaviour,
face):
super().__init__(name, attitude, behaviour, face)
What did I do here? It’s very similar to coding the parent class. Note the differences though:
- We start by defining the subclass
GoodBoss
. See how it has “Boss” between the brackets? This will ensure theGoodBoss
class inherits everything from theBoss
class. - In the init dunder, we have to specify
self
as well as all of the attributes defined in the parentBoss
class we’re inherting from. We can then add whatever ‘GoodBoss’ unique attributes we want, such as a “laugh” attribute (good bosses laugh right?). In this case, I’m not adding any, thus the last attribute you see isface
. - The
super()
statement is probably the most confusing. It relates to the inheritance from the base class.
I’d be doing you a disservice trying to explain super() in one bullet point so I’m going to direct you to where I read up on it. The 3rd answer in this Stack Overflow thread is amazing as is this Programiz article.
Phew! Okay. Next up, we can define some GoodBoss specific class functions. These are functions that can only be used by an object created using the GoodBoss
class:
def nurture_talent(self):
#A good boss nurtures talent making employees happy!
print("The employees feel all warm and fuzzy then put their talents to good use.")
def encourage(self):
#A good boss encourages their employees!
print("The team cheers, starts shouting awesome slogans then gets back to work.")
What does a good boss do? They nurture talent to help employees grow! They also encourage their teams to keep them motivated!
These two class functions print out the specified message when called. If this were a game, rather than just printing, we could have these functions perform transactions like “increase employee_happiness
by 20 points”, or something similar.
In the same way, we can define a BadBoss
subclass. You can find the BadBoss
subclass code in our code repo here.
Who’s the Boss?!
Time for some fun! I’ll be the good boss; Bob can be the bad boss. (Sorry Bob!).
The easiest way to test this out is to import the code into the Python interactive shell.
I’ve created a Python file boss_class.py
and am initiating the Python shell from the same folder.
from boss_class import Boss, GoodBoss, BadBoss
Once imported, we can create a “standard” Boss
, a GoodBoss
or a BadBoss
. Let’s start with the good one!
julian = GoodBoss("Julian", "Positive", "Sociable", "Smiling")
We can then use the class functions associated with both the Boss
class and GoodBoss
subclass:
julian.attitude
‘Positive’
julian.get_behaviour()
‘Sociable’
julian.nurture_talent()
The employees feel all warm and fuzzy then put their talents to good use.
I wish I really had that effect on people! Also, this is inheritance in action: we inherited the get_behaviour
function from the Boss
class! Woohoo!
Ending on a low
I know we’re on a roll, but Bad Bosses always have a way of ruining things:
bob = BadBoss("Bob", “Crazy”, "Anti-Social", "Scowl of Hate")
bob.face
'Scowl of Hate'
bob.get_attitude()
‘Crazy’
bob.hoard_praise()
The employees feel cheated and start plotting Bob's demise while he stares at his own reflection.
bob.yell()
Everyone stares while Bob yells. Someone shouts, 'Won't somebody PLEASE think of the children?!’
Bob storms off, everyone comforts the victim and one person offers to arrange an 'accident' for Bob.
Disclaimer: I love Bob (we all know he’s the best thing since sliced bread!).
Conclusion
How cool are classes, subclasses and inheritance?
Not only has this helped me better plan my code but it’s also allowed me to better appreciate other code. I can only imagine how many classes and subclasses exist in video games (World of Warcraft for example!).
Once you get the hang of them, classes really are a pleasure to use. They’re a series of set and forget templates/blueprints for you to call at any time. So many possibilities…
Oh, and speaking of templates. I created a framework/blank class and subclass template for Day 77 of our 100 days of code challenge. Check it out here!
Keep Calm and Code in Python!
— Julian
(Psst! Did anyone get the Simpsons Reference?)