Click to share! ⬇️

Basic Python Inheritance

A key concept of object-oriented programming is that of inheritance. In this tutorial, we’re going to see how basic inheritance works in Python. Inheritance defines a way for a given class to inherit attributes and methods (variables and functions) from one or more base classes. This technique gives programmers the ability to centralize common functionality and data in a single place instead of having it spread out and duplicated across multiple classes. Let’s look at a few examples of Inheritance in Python now.


A Python Class

class Superclass():
    def __init__(self, color, height, width):
        self.height = height
        self.color = color
        self.width = width

    def does_stuff(self):
        print('This method does stuff')

Above is a simple Python class. It has three attributes and one method.


Inheriting From A Superclass

class Subclass(Superclass):
    pass


obj1 = Subclass('Red', '5 feet', 100)

In this code here, we define a new class of Subclass and make it inherit from Superclass. We use the pass keyword in this Subclass to show that it has no data or behavior of its own. Then we create an object out of this Subclass and assign it to obj1.


The Child Has Now Inherited Attributes And Methods

print(type(obj1))
print(isinstance(obj1, Subclass))
print(obj1.color)
print(obj1.height)
print(obj1.width)
obj1.does_stuff()
<class '__main__.Subclass'>
True
Red
5 feet
100
This method does stuff

What this code here does is use type() and isinstance() to show that obj1 is an object of type Subclass. Further, since it inherits from Superclass, it has access to all of the attributes and methods of the parent class.


Classes Without Inheritance

class Inputdevice:
    def __init__(self, devicetype, inputconnector, bluetooth, manufacturer):
        self.devicetype = devicetype
        self.manufacturer = manufacturer
        self.inputconnector = inputconnector
        self.bluetooth = bluetooth


class Outputdevice:
    def __init__(self, devicetype, connector, manufacturer, outrate):
        self.devicetype = devicetype
        self.manufacturer = manufacturer
        self.outrate = outrate
        self.connector = connector


class IODevice:
    def __init__(self, devicetype, connector, manufacturer, outrate):
        self.devicetype = devicetype
        self.manufacturer = manufacturer
        self.outrate = outrate
        self.connector = connector


input1 = Inputdevice("Keyboard", "usb", True, "Lenovo")
io1 = IODevice("Flash Drive", "usb", "Sandisk", "35MB ps")
output1 = Outputdevice("Monitor", "HDMI", "Samsung", "18Gbps")

print("This device has a " + input1.inputconnector + " connector")
print(io1.manufacturer + " is the device manufacturer")
print(input1.manufacturer + " " + input1.devicetype)
print(output1.manufacturer + " " + output1.devicetype)
This device has a usb connector
Sandisk is the device manufacturer
Lenovo Keyboard
Samsung Monitor

In this code, you can see there are three classes. There’s an Inputdevice, Outputdevice, and IOdevice class. Each one of these classes represents a type of peripheral, and each of them has a set of attributes that are relevant to that peripheral type. So Inputdevices have a devicetype and a manufacturer along with an inputconnector and the ability to use bluetooth. An IOdevice also has a devicetype and a manufacturer, but they have a generic connector instead of an inputconnector. Outputdevices have a devicetype and manufacturer too, while also having an outrate and a connector. The output from running the code gives us what we would expect to see. At this state, each of these is a standalone implementation of it’s own class but there’s a considerable amount of duplication among the data that each class holds. We can do better using inheritance.


Rewriting Classes With Inheritance

class Peripheral:
    def __init__(self, devicetype, manufacturer):
        self.devicetype = devicetype
        self.manufacturer = manufacturer


class Outputperipheral(Peripheral):
    def __init__(self, devicetype, manufacturer, connector, outrate):
        super().__init__(devicetype, manufacturer)
        self.outrate = outrate
        self.connector = connector


class Inputdevice(Peripheral):
    def __init__(self, devicetype, inputconnector, bluetooth, manufacturer):
        super().__init__(devicetype, manufacturer)
        self.inputconnector = inputconnector
        self.bluetooth = bluetooth


class Outputdevice(Outputperipheral):
    def __init__(self, devicetype, connector, manufacturer, outrate):
        super().__init__(devicetype, manufacturer, connector, outrate)


class IODevice(Outputperipheral):
    def __init__(self, devicetype, connector, manufacturer, outrate):
        super().__init__(devicetype, manufacturer, connector, outrate)


input1 = Inputdevice("Keyboard", "usb", True, "Lenovo")
io1 = IODevice("Flash Drive", "usb", "Sandisk", "35MB ps")
output1 = Outputdevice("Monitor", "HDMI", "Samsung", "18Gbps")

print("This device has a " + input1.inputconnector + " connector")
print(io1.manufacturer + " is the device manufacturer")
print(input1.manufacturer + " " + input1.devicetype)
print(output1.manufacturer + " " + output1.devicetype)
This device has a usb connector
Sandisk is the device manufacturer
Lenovo Keyboard
Samsung Monitor

The original code is now rewritten to make use of inheritance. We have a better organization of these classes and made it easier to introduce new classes by implementing some inheritance and class hierarchy. Running this new code, you can see that the output is the same as before. So we’re getting the same results, but with better code organization, which is one of the main benefits of inheritance. We now can add properties that are specific to each kind of peripheral just in one place and would only have one place to edit them if we needed to change the names of any of these attributes in the future.

Click to share! ⬇️