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
Square
andCircle
inherit from theForm
class.- Lines 8 and 13
call the
__init__
method of theForm
class.
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:
Circle
andSquare
both 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 thesuper
function, more precisely through the linessuper().__init__(x,y)
. This code calls the initialisation function ofForm
with the instance to be initialised and the corresponding arguments. Otherwise, the instance variablesx
andy
would not be set for the instances ofCircle
andSquare
.
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
Triangle
class so that it inherits fromForm
.How would you write the code to add an
area()
method for theTriangle
class? Should thearea()
method be moved to theForm
base class and inherited byCircle
,Square
andTriangle
? What problems would this change cause?