Classes and inheritance¶
Inheritance in Python is simpler and more flexible than inheritance in compiled languages such as Java and C++ because the dynamic nature of Python does not impose as many restrictions on the language.
To see how inheritance is used in Python, let’s start with the Square and
Circle classes we discussed earlier and generalise them.
If we now want to use these classes in a drawing program, we need to define
where on the drawing surface an instance should be located. We can do this by
defining x and y coordinates for each instance:
1>>> class Square:
2... def __init__(self, length=1, x=0, y=0):
3... self.length = length
4... self.x = x
5... self.y = y
6...
7>>> class Circle:
8... def __init__(self, diameter=1, x=0, y=0):
9... self.diameter = diameter
10... self.x = x
11... self.y = y
12...
This approach works, but leads to a lot of repetitive code when you increase the
number of shape classes, as you probably want every shape to have this
positional information. This is a standard situation for using inheritance in
object-oriented languages. Instead of defining the x and y variables in
each shape class, you can abstract them into a general shape class and have each
class that defines a particular shape inherit from that general class. In
Python, this technique looks like this:
1>>> class Form:
2... def __init__(self, x, y):
3... self.x = x
4... self.y = y
5...
6>>> class Square(Form):
7... def __init__(self, length=1, x=0, y=0):
8... super().__init__(x, y)
9... self.length = length
10...
11>>> class Circle(Form):
12... def __init__(self, diameter=1, x=0, y=0):
13... super().__init__(x, y)
14... self.diameter = diameter
15...
- Lines 6 and 11
SquareandCircleinherit from theFormclass.- Lines 8 and 13
call the
__init__method of theFormclass.
There are generally two requirements when using an inherited class in Python,
both of which you can see in the code of the Circle and Square classes:
The first requirement is to define the inheritance hierarchy, which you do by specifying the classes that are inherited from in parentheses immediately after the name of the class, which is defined with the class keyword:
CircleandSquareboth inherit fromForm.The second element is the explicit call to the
__init__method of the inherited class. This is not done automatically in Python, but mostly through thesuperfunction, more precisely through the linessuper().__init__(x,y). This code calls the initialisation function ofFormwith the instance to be initialised and the corresponding arguments. Otherwise, the instance variablesxandywould not be set for the instances ofCircleandSquare.
Inheritance also comes into play when you try to use a method that is not
defined in the base classes but in the superclass. To see this effect, define
another method in the Form class called move that moves a shape in the
x and y coordinates. The definition for Form is now:
1>>> class Form:
2... def __init__(self, x=0, y=0):
3... self.x = x
4... self.y = y
5... def move(self, delta_x, delta_y):
6... self.x = self.x + delta_x
7... self.y = self.y + delta_y
8...
If you take the parameters delta_x and delta_y of
the method move in the __init__ methods of Circle and Square,
you can for example execute the following interactive session:
>>> c = Circle(3)
>>> c.move(4, 5)
>>> c.x
4
>>> c.y
5
The class Circle in the example does not have a move method defined
directly in itself, but since it inherits from a class that implements move,
all instances of Circle can use the move method. In OOP terms, one could
say that all Python methods are virtual – that is if a method does not exist in
the current class, the list of superclasses is searched for the method and the
first one found is used.
Checks¶
Rewrites the code for a
Triangleclass so that it inherits fromForm.How would you write the code to add an
area()method for theTriangleclass? Should thearea()method be moved to theFormbase class and inherited byCircle,SquareandTriangle? What problems would this change cause?