Back to: Python Programming
The super() function is a function used in a child class to call methods from a parent class (superclass).
It allows you to extend the functionality of the inherited methods.
The super() function in Python provides a way to access methods and attributes of a parent or sibling class from within a subclass. It is primarily used in object-oriented programming to support method overriding and inheritance, facilitating code reusability and maintainability.
As an example we’ll create some shape objects, we’ll first need to set up the classes and instantiate objects with a constructor with the attributes of our shapes – like colour, filled or outline, dimensions, then we need to assign them.
class Circle:
def __init__(self, colour, filled, radius):
self.colour = colour
self.filled = filled
self.radius = radius
class Square:
def __init__(self, colour, filled, width):
self.colour = colour
self.filled = filled
self.width = width
class Triangle
def __init__(self, colour, filled, width, height):
self.colour = colour
self.filled = filled
self.width = width
self.height = height
In programming, we try not to repeat ourselves! We have copy/paste so repeating code chunks is not difficult, but imagine that we needed to change an attribute, like filled to is_filled, to achieve this we’d manually have to find every instance of filled and modify it. If we miss one, we introduce an error.
What do all of these classes have in common? They all share the attributes of colour and filled. The ways these attributes are different is that Circle has a radius attribute, Square has a width attribute and Triangle has width and height.
It is always better to write your code ONCE then try to re-use it. This is where inheritance and the super() function can come in handy.
Making a parent class (superclass)
We are going to take the repeated attributes of colour and filled and place them within a parent class. These children classes will then inherit those attributes.
First we create a class Shape, then each of the children classes are going to inherit from the parent:
class Shape:
pass
class Circle(Shape):
...
class Square(Shape):
...
class Triangle(Shape):
...
We need to set up a constructor for Shape then pass in the colour and filled, then we will assign these attributes.
class Shape:
def __init__(self, colour, filled):
self.colour = colour
self.filled = filled
We don’t need to manually assign these attributes within each of the constructors for the children, instead, within the constructor for each of the children classes, we have to call the constructor for the parent, also known as the superclass of Shape. This will eliminate the two lines of code for each child class describing colour and filled, replacing them with with the superfunction:
super().__init__(colour, filled)
We still need radius for the circle, width for the square and width, height for the triangle. The code now looks like this:
class Shape:
def __init__(self, colour, filled):
self.colour = colour
self.filled = filled
class Circle(Shape):
def __init__(self, colour, filled, radius):
super().__init__(colour, filled)
self.radius = radius
class Square(Shape):
def __init__(self, colour, filled, width):
super().__init__(colour, filled)
self.width = width
class Triangle(Shape):
def __init__(self, colour, filled, width, height):
super().__init__(colour, filled)
self.width = width
self.height = height
Now we can construct a few objects to make sure this works.
class Shape:
def __init__(self, colour, filled):
self.colour = colour
self.filled = filled
class Circle(Shape):
def __init__(self, colour, filled, radius):
super().__init__(colour, filled)
self.radius = radius
class Square(Shape):
def __init__(self, colour, filled, width):
super().__init__(colour, filled)
self.width = width
class Triangle(Shape):
def __init__(self, colour, filled, width, height):
super().__init__(colour, filled)
self.width = width
self.height = height
circle = Circle(colour="red", filled=True, radius=5)
square = Square(colour="blue", filled=False, width=6)
triangle = Triangle(colour="yellow", filled=False, width=10, height=7)
print(circle.colour)
print(circle.filled)
print(f"The square has width {square.width}cm")
print(f"The square has area {square.width*square.width} cm squared")
print(f"The triangle has height {triangle.height}cm")
print(f"The triangle has area {0.5*triangle.width*triangle.height}cm squared")
Outputs:
red
True
The square has width 6cm
The square has area 36
The triangle has height 7cm
The triangle has area 35.0
Extend the functionality of the method
Within out Shapes class we will create a method called describe.
class Shape:
def __init__(self, colour, filled):
self.colour = colour
self.filled = filled
def describe(self):
print(f"The shape is {self.colour} and {'filled' if self.filled else 'not filled'}")
class Circle(Shape):
def __init__(self, colour, filled, radius):
super().__init__(colour, filled)
self.radius = radius
class Square(Shape):
def __init__(self, colour, filled, width):
super().__init__(colour, filled)
self.width = width
class Triangle(Shape):
def __init__(self, colour, filled, width, height):
super().__init__(colour, filled)
self.width = width
self.height = height
circle = Circle(colour="red", filled=True, radius=5)
square = Square(colour="blue", filled=False, width=6)
triangle = Triangle(colour="yellow", filled=False, width=10, height=7)
circle.describe()
square.describe()
triangle.describe()
Outputs:
The shape is red and filled
The shape is blue and not filled
The shape is yellow and not filled
Method over-riding
If we have a method in each child class with the same name describe, the child version will override the parent. We can, however, extend the functionality of a method from a parent, we can use the superfunction. Not only do I want to use the describe method of the child, I also want to use the describe method of the parent. Within the describe method of the child class, we can use the super() function to access the describe method of the parent. We are essentially extending the functionality of the describe method.
The final code looks like this:
class Shape:
def __init__(self, colour, filled):
self.colour = colour
self.filled = filled
def describe(self):
print(f"The shape is {self.colour} and {'filled' if self.filled else 'not filled'}")
class Circle(Shape):
def __init__(self, colour, filled, radius):
super().__init__(colour, filled)
self.radius = radius
def describe(self):
print(f"The shape is a circle with an area of {3.14 * self.radius * self.radius}cm^2")
super().describe()
class Square(Shape):
def __init__(self, colour, filled, width):
super().__init__(colour, filled)
self.width = width
def describe(self):
print(f"The shape is a square with an area of {self.width * self.width}cm^2")
super().describe()
class Triangle(Shape):
def __init__(self, colour, filled, width, height):
super().__init__(colour, filled)
self.width = width
self.height = height
def describe(self):
print(f"The shape is a triangle with an area of {self.width * self.height / 2}cm^2")
super().describe()
circle = Circle(colour="red", filled=True, radius=5)
square = Square(colour="blue", filled=False, width=6)
triangle = Triangle(colour="yellow", filled=True, width=7, height=8)
circle.describe()
square.describe()
triangle.describe()
Outputs:
The shape is a circle with an area of 78.5cm^2
The shape is red and filled
The shape is a square with an area of 36cm^2
The shape is blue and not filled
The shape is a triangle with an area of 28.0cm^2
The shape is yellow and filled
OOP Class Inheritance and Private Class Members – 16m:11s