Object Inheritance in Python
While Python isn’t purely an object-oriented language, it’s flexible enough and powerful enough to allow you to build your applications using the object-oriented paradigm. One of the ways in which Python achieves this is by supporting inheritance, which it does with super()
.
By the end of this course, you’ll be able to:
- Compose a class
- Use
super()
to access parent methods - Understand single and multiple inheritance
In this lesson, you’ll cover how to use super()
to access a parent class’s constructor:
class Rectangle:
def __init__(self, length, width):
self.length = length
self.width = width
def area(self):
return self.length * self.width
def perimeter(self):
return 2 * self.length + 2 * self.width
class Square(Rectangle):
def __init__(self, length):
super().__init__(length, length)
00:00
Welcome to Inheritance and super()
in Python. My name is Chris and I will be your guide. This course is split up into three lessons. The first lesson talks about inheritance and objects and classes in Python, and quickly shows you how to use the super()
function to get at the parent attributes and methods in inheritance. The second and third lessons talk about single and multiple inheritance and how to use super()
to get at those objects as well.
00:24 First off, a quick warning. The syntax for inheritance has changed between Python 2 and Python 3. All the examples I’ll be using in this course will be based on Python 3.
00:33 So, let’s get started. In this lesson, I’ll be talking about classes and objects, when to use them, why, and how. So, what is an object? An object is just a way of grouping data and methods together, usually for things that belong together and help you organize your code.
00:48 Frequently, an object maps to something in the real world. If you’re writing software that describes a class schedule, you might have a person object with a name and an address attribute, and methods on that for adding that person to a course or saving their data. Similarly, if you were writing accounting software, your balance sheet object might have a list of assets and a list of liabilities as the attributes, and a method for totaling the assets or taking a report. A class defines how to make an object, and is actually in Python how you create the object itself, which is called instantiation.
01:24
I’m going to start with some examples that are based on geometric shapes. If you’re coding along with me, I’m putting it inside of a file called shapes.py
.
01:32
This is the simplest possible class. It’s two lines. It starts with the keyword class
and the name of the class, Square
. By convention in Python, you always capitalize the name of your class.
01:45
The pass
keyword tells Python that there’s nothing else in this class besides an empty definition. If you open up a REPL and import the Square
class from shapes
, you can then instantiate it by calling it. The Square
, on the right-hand side, capital S
, is my class.
02:02
I call it using the parentheses ()
, and I end up with an object that I’ve named square
. I can now add attributes to that square
, maybe a .length
of 3
, and I can examine that square
by using the built-in function called dir()
.
02:18
There’s a lot of content here. Don’t worry about it too much. There’s just two things I want to point out. On the bottom right-hand side, you’ll notice 'length'
.
02:27
When I added the .length
attribute to square
, dir()
shows that it’s there. In the top left, there’s a special method '__class__'
that contains information about the class the object came from. If I look at that now in the REPL,
02:42
it produces a class
object that says this is a Square
. You can always figure out what class an object comes from by examining this property. Now I want to add some complexity to the Square
.
02:56
First off, you’ll recall I added an attribute .length
. Well, the Square
without a .length
isn’t useful, so I want to make sure that a .length
is always there.
03:06
You can do this by changing the constructor. The constructor in Python is called .__init__()
. This method gets called every time a class constructs an object.
03:18
The default one doesn’t take any parameters. I’ve changed this one to take a parameter called .length
. I then store that on the object itself that gets created from the class.
03:29
Now it won’t be possible to create a Square
without a length
being defined and that attribute stored on the object. In addition to storing the .length
, I’ve also defined two methods, .area()
and .perimeter()
.
03:43
These return the area and perimeter of the Square
itself, by doing math on the .length
.
03:51
You can see this inside of the REPL. Importing from Square
like before, now I’m passing in the length
of 3
as part of the constructor. I get my .length
, it returns a value 3
. I can call the .area()
method, I get 3 * 3 is 9
. And once again, I can look at dir()
to examine the object.
04:13
In addition to having the '__class__'
as before, on the bottom right side now you can see 'area'
, 'length'
, and 'perimeter'
, the methods and attributes that were defined in the class. Great, so I’ve got my square. Now I want to add another shape. This time, it’s a Rectangle
. This is going to be very similar to my Square
.
04:36
Instead of needing a length
on its own, I need a length
and a width
. Like before, I used the .__init__()
method to pass in those as parameters and save them on the object.
04:47
And also like before, I have .area()
and .perimeter()
methods to do the calculations based on the .length
and .width
of the Rectangle
.
04:57 Once again, import it from the REPL,
05:01
passing in a length
and a width
.
05:04 And I get the expected result.
05:08
The two classes I’ve defined so far, the Square
and the Rectangle
, are very, very similar. This is a problem. If it turns out there was a bug in the .area()
method of one, because I duplicated it in the other, I probably have to fix it in two places.
05:21
One of the ways of simplifying this is by using inheritance. Instead of defining the Square
and the Rectangle
separately, I’m going to define the Square
based on the Rectangle
, replacing the code you see here with the new code at the bottom.
05:35
In this case, Square
, having Rectangle
in brackets, inherits from the Rectangle
object. I don’t have to define anything new on it.
05:45
It will inherit anything that I don’t override from the Rectangle
. The .__init__()
method does need to be overridden. The Rectangle
takes a length
and a width
. The Square
only takes a length
, so I need to redefine this method. This is where super()
comes in.
06:01
super()
allows me to access the parent’s methods—in this case, the parent Rectangle.__init__()
method—and I’m going to pass in a length
for the Rectangle
length
and width
.
06:13
I don’t have to specify anything else. The .area()
and .perimeter()
will now come from the Rectangle
class from before.
06:22
Inside of shapes.py
, I’ve replaced the old Square
definition with this new inherited code. Like before, I can use the REPL and import the Square
, instantiate it with a length
of 3
. If I look at the .__class__
, not surprisingly, it’s a Square
. If I look at the dir()
of the object, you’ll see a few new things. For starters, at the bottom, the 'width'
, 'perimeter'
, 'length'
, and 'area'
are all there.
06:49
The .area()
, .perimeter()
, and .width
are inherited from the Rectangle
class. The .length
is passed in, in the constructor.
06:57
I can also look at the .__bases__
attribute of the .__class__
attribute. This can tell you where your inheritance is from. Because Square
inherits from Rectangle
, the .__bases__
value shows the Rectangle
class. In the next lesson, I’m going to show you how to use super()
to look at different methods and attributes inside of single inheritance.
swapniltambe93 on May 4, 2020
Hi Christopher, thanks for this amazing video lecture. I just have one query which as follows, why are you using lenght twice here in class Square(Rectangle): def init(self, length): super().init(length, length)
Roy Telles on Aug. 11, 2020
I think the reason for passing length
twice in super().__init__(length, length)
is because a Square’s width
is essentially its length. And since a Square is a Rectangle, we need to pass its length
again to the Rectangle’s width
parameter.
Christopher Trudeau RP Team on Aug. 12, 2020
Yes Roy, you’re right! The Rectangle class takes two parms its width and its length. The Square inherits from Rectangle and needs to pass in those same to parms. In the case of the Square the length and width are the same thing, so it gets passed in twice.
Christopher Trudeau RP Team on Aug. 12, 2020
I know this answer is very late, but in case anyone else is curious, I don’t use a text editor to do these demos. I find it hard to type and talk at the same time, so I wrote a custom utility that makes it look like I’m doing that. The tool uses Urwid, a curses-like command line GUI thing and Pygments for the colourization.
It is available on PyPI and the code is here:
(the pedantic answer to your question is Vim though, I’m old and old-school :) )
Dan B on Nov. 13, 2020
The from shapes import Square
bit was a surprise to me! Where can I learn about how to structure code in python?
Christopher Trudeau RP Team on Nov. 13, 2020
Hi Dan,
If you’re interested in packages and modules in Python, you might like the following course:
realpython.com/courses/python-modules-packages/
Happy coding!
Dan B on Nov. 13, 2020
Thanks.
Become a Member to join the conversation.
fd on April 12, 2020
Many thanks for the interesting course! May i ask what text editor did you use? :)