Python inheritance is when a subclass uses the code from another class. Inheritance is an essential feature in object-oriented languages like Python that makes coding easier and more efficient.
Python is an object-oriented language, which means that it supports creating reusable blocks of code to help make code more efficient. One of the ways in which this happens is through inheritance, where one subclass can use code from another class.
For example, you may have a class that stores “bank accounts”, and want to create a subclass that stores “gold bank accounts” that can reference attributes in the “bank accounts” existing class.
In this tutorial, we are going to break down the basics of inheritance in Python. We are also going to discuss how parent and child Python classes work, and how to override attributes and methods when you’re working with classes objects.
Python Inheritance
Inheritance is a term that is used to describe a Python class within another class. Classes called subclasses
or child classes
can inherit values from parent classes
, similar to how children inherit characteristics from their parents in the real world.
Inheritance is useful because it allows us to create subclasses
that have the same value types as a parent class, without having to declare those types multiple times.
Parent Classes
Parent classes (also called base classes
create the master structure that subclasses can access. We can create multiple subclasses without having to declare the same set of common values over again that derived class methods from the parent class.
Let’s use an example to illustrate how this would work in action. Say that we had a program that works with two different bank account types: parent and child.
Both of these accounts are bank accounts, and so they will have similar values. But each of these accounts may require their own unique information. For example, a parent’s account may support an overdraft, whereas the child’s account may only work with their balance.
So, if we wanted to create a program with these values, we would first define a class for our bank account (a parent class) then create child classes for the two types of bank accounts—parent and child—that we want to support.
Here’s an example of declaring a parent class for a bank account:
class BankAccount: def __init__(self, forename, surname, balance): self.forename = forename self.surname = surname self.balance = balance
We have created the class BankAccount
which stores three values: forename, surname, and balance. We can also add methods to our class, like so:
class BankAccount: def __init__(self, forename, surname, balance): self.forename = forename self.surname = surname self.balance = balance def getDetails(self): print("Forename: ", self.forename) print("Surname: ", self.surname) def getBalance(self): print("Balance: $ ", self.balance)
Our class now stores three values, as well as two new methods: details and balance. The details
method can be used to find out our account holder’s forename and surname, and the balance
method will return the account holder’s balance.
Every method and variable that we declare in our BankAccount
class will be accessible in our child class.
To illustrate our class in action, let’s create an example bank account. We can do so using the following code:
account = BankAccount("John", "Appleseed", 100)
This will create an account for John Appleseed
which contains $100. Now that we have our account ready, we can start to reference it like we would with any other class. Here’s an example of us running the getBalance()
method within our bank account to find out how much money we have:
print(account.getBalance())
Our program returns the following:
Balance: $ 100
Child Classes
In the above example, we declared a parent class which stores bank accounts. But what if we want to store information about a specific type of account like a child’s under 18 account? That’s where child classes come in.
Child classes, or subclasses, inherit values from the parent class. This means that each child class will be able to reference the methods and variables that we declare in our parent class.
So, let’s say that we want to create a child class for a ChildBankAccount
. This account should be able to return a user’s bank account information—their name and balance—and should also have a new value called restricted
. This value will be stored on a child’s account because they are under 18, and are not eligible for a full bank account.
In order to create a child class, we can use the following code:
class ChildBankAccount(BankAccount):
The ChildBankAccount
class becomes a child of the BankAccount
class because BankAccount
is enclosed within parentheses. If we want our child class to have exactly the same values as our parent class—BankAccount
—we can use the pass
keyword like this:
class ChildBankAccount(BankAccount): pass
But as we discussed earlier, our child account will need to store a special value: a variable that says that the user’s account is restricted.
To accomplish this goal, we are going to add a new value called restricted
to our child class. We can do this using the following code:
class ChildBankAccount(BankAccount): def __init__(self, forename, surname, balance, restricted=True): self.forename = forename self.surname = surname self.balance = balance self.restricted = restricted def isRestricted(self): print("This account is restricted as the user is under 18.")
Now, let’s break down our code.
In the above code, we state that we want our ChildBankAccounts to hold four values: forename, surname, balance, and restricted.
The first three—forename, surname, and balance—are the same as our parent class values but restricted
is new, and it is exclusive to our child class. By default, restricted
is set to True
.
"Career Karma entered my life when I needed it most and quickly helped me match with a bootcamp. Two months after graduating, I found my dream job that aligned with my values and goals in life!"
Venus, Software Engineer at Rockbot
So if we create a standard BankAccount
(not a ChildBankAccount
), we will not be able to access the restricted
value. Similarly, we won’t be able to access the isRestricted
method unless we create a ChildBankAccount
.
Here’s an example of us creating a ChildBankAccount
and using the getBalance()
and isResticted()
methods to learn more about our class:
child_account = ChildBankAccount("Bill", "Appleseed", 100) print(child_account.getBalance()) print(child_account.isRestricted())
Our code returns the following:
Balance: $ 100 This account is restricted as the user is under 18.
As you can see, our program first defines a new ChildBankAccount
for Bill Appleseed
, whose account holds $100. Then, our program executes the getBalance()
method in our class, which returns the user’s balance. getBalance()
is declared in our parent class, BankAccount
, but is accessible to ChildBankAccount
through inheritance.
Our program also executes the isRestricted()
method, which states that the child’s account is restricted because they are under the age of 18. This class is declared in ChildBankAccount
, though, which means that it is not accessible to our parent class BankAccount
. If we wanted to create a restricted BankAccount
, we would need to change the parent class.
Redefining Parent Methods
In our above example, we declared a parent class called BankAccount
which stores information for bank accounts. We also created a child class called ChildBankAccount
which stores information for account holders under the age of 18. This class inherited the methods from the BankAccount
class and also created the isRestricted()
method.
But what if we want to modify an existing parent class method? Say we want our BankAccount
balance to return a message with their balance and a message stating You are eligible for an overdraft
, but we don’t want this to appear for ChildBankAccount
holders.
To do this, we need to override our parent method.
Here’s the code for our revised parent method, BankAccount
, which now prints a message to account holders to say they are eligible for an overdraft when they check their balance:
class BankAccount: def __init__(self, forename, surname, balance): self.forename = forename self.surname = surname self.balance = balance def getDetails(self): print("Forename: ", self.forename) print("Surname: ", self.surname) def getBalance(self): print("Balance: $ ", self.balance) print("You are eligible for an overdraft.")
Now, if we create a new BankAccount
for John Appleseed
and print out his balance, we’ll see a message stating You are eligible for an overdraft
. Here’s an example of us declaring a new account and checking its balance:
account = BankAccount("John", "Appleseed", 100) print(account.getBalance())
Our code returns the following:
Balance: $ 100 You are eligible for an overdraft.
But this change also means that our ChildBankAccount
, which inherits its values from BankAccount
, will also see the message. Here’s an example of us creating a ChildBankAccount
and checking its balance now that our BankAccount
parent class has changed:
child_account = ChildBankAccount("Bill", "Appleseed", 100) print(child_account.getBalance())
Our code returns:
Balance: $ 100 You are eligible for an overdraft.
Because children are generally not allowed overdrafts, we will need to make a change to our code. Now, in order to do so, we have to modify our ChildBankAccount
class and declare a new getBalance()
function.
Here’s the code for our ChildBankAccount
from above:
class ChildBankAccount(BankAccount): def __init__(self, forename, surname, balance, restricted=True): self.forename = forename self.surname = surname self.balance = balance self.restricted = restricted def isRestricted(self): print("This account is restricted as the user is under 18.")
We need to change this code to add a new function: getBalance()
. This function will work in the same way as the one we declared in our parent class, but it will not include the message about overdrafts. Here’s the code that we would add to declare our new function:
… def getBalance(self): print("Balance: $ ", self.balance)
Let’s try to retrieve our child’s balance now:
child_account = ChildBankAccount("Bill", "Appleseed", 100) print(child_account.getBalance())
Our code returns the following:
Balance: $ 100
In the above example, we have overwritten the getBalance()
method in the ChildBankAccount
child class. Our new getBalance()
method for ChildBankAccount
only shows the user’s balance. But in our BankAccount
class, the getBalance()
method shows both the user’s balance and the message You are eligible for an overdraft
.
Overriding parent methods can be useful when you have multiple child methods which may use similar methods to their parents, but require their own specific changes to be made. Like in the case above, we want our parent bank accounts to see an overdraft message, but not our child bank accounts, so we overrode our parent method in ChildBankAccount
.
Conclusion
Inheritance is used in object-oriented programming to help you create subclasses that can store values already declared in a parent class. This is useful when you are creating similar classes that will store similar values because you can use inheritance to create those classes without repeating your code multiple times over.
In this tutorial, we explored the role of inheritance in Python. We also discussed how inheritance and parent and child classes work, then we explored how to override parent methods. Now you’re ready to work with classes and inheritance like a Python expert!
About us: Career Karma is a platform designed to help job seekers find, research, and connect with job training programs to advance their careers. Learn about the CK publication.