Reputation: 902
I'm creating a GUIclass that uses Frame() as its base class.
In my GUIclass’s init method I want to create a Frame widget
Right now I have:
class GUIclass(Frame):
def __init__(self, parent):
frame = Frame(self, parent)
But I've seen this elsewhere for the third line:
Frame.__init__(self, parent)
I'm new to programming, python and definitely inheritance and I wanted to know if I understand the difference between the two correctly. I did a lot of researching and reading, I promise, but I couldn't quite find anything that made it completely clear:
In the first situation I don't call the init method as I created a Frame object (frame) and when an object is created its init method is called implicitly by python.
In the second scenario, one is calling the init method on the class (which I believe is totally legit?) because a Frame object wasn't created, so therefore wouldn't do it automatically.
Is that right?
I've also seen:
frame = Frame.__init__(self, parent)
which really threw me off. Is this just someone doing something redundant or is there a reason for this?
Thank you for your help, I want to take it slow for now and make sure I fully understand any and every line of code I write as I go rather than writing and running a whole program I half understand.
Upvotes: 12
Views: 1453
Reputation: 43
You'll have to use Frame.__init__(self, parent)
as Tkinter doesn't support super calls
Upvotes: 1
Reputation: 59436
You should call
super(GUIclass, self).__init__(parent)
This is the proper way to call (all) your inherited __init__()
method(s). It has in many cases identical results compared to the mentioned
Frame.__init__(self, parent)
which only lacks the abstraction concerning the inheritance relationships and states the class Frame
as the one and only class whose __init__()
method you might want to call (more about that later).
The also mentioned
frame = Frame(self.parent)
is wrong in this context. It belongs to another pattern of object relationship, namely contents relationship instead of inheritance relationship (which you aim at). It will create a new object of class Frame
instead of initializing the Frame
parts of yourself; in inheritance relationships you are a Frame
, so you have to initialize yourself
as one as well as initializing your specialized parts (which is done in the rest of your __init__()
method). In contents relationship models you merely have a Frame
.
Now, what about that "slight" difference I mentioned above between calling super(GUIclass, self).__init__(parent)
and Frame.__init__(self, parent)
?
To understand that you need to dig deeper into inheritance relationships and the various possibilities these offer, especially with multiple inheritance.
Consider a diamond-shaped relationship model which looks like this:
Frame
/ \
GUIclass SomeOtherClass
\ /
AnotherClass
In your current scenario you only have the top left two classes, but one never knows what's going to come, and you should always code in a way so that the next user of your code keeps all options.
In this diamond-shaped pattern you have AnotherClass
which inherits GUIClass
and SomeOtherClass
which in turn both inherit Frame
.
If you now use the pattern Frame.__init__(self, parent)
in both GUIclass
and SomeOtherClass
, then calling their __init__()
methods from the __init__()
method of AnotherClass
will result in a doubled calling of the Frame
's __init__()
method. This typically is not intended, and to take care that this does not happen, the super
call was invented. It takes care that a decent calling order calls each of the __init__()
methods only and exactly once.
Upvotes: 8