Reputation: 1083
While wrestling with how to subclass a tkinter Frame
and LabelFrame
so they sat on the correct parent, I found a lot of answers suggested that super().__init__
was better than BaseClass.__init()__
when subclassing.
So I tried it, to see what the fuss was about, and it doesn't seem to work at all. In python 2.7, it complains about the types of the arguments. In 3.4, it says there are multiple definitions for master. With super commented out as below, it works as expected. What am I doing wrong?
# import Tkinter as tki # py 2.7
import tkinter as tki # py 3.4
class App(tki.LabelFrame):
def __init__(self, parent):
tki.LabelFrame.__init__(self, master=parent, text='inner')
# super().__init__(self, master=parent, text='inner') #py 3.4
# super(App, self).__init__(self, master=parent, text='inner') #py 2.7
# super(App, self).__init__(master=parent, text='inner') #py 2.7
self.quit = tki.Button(self, text='quit', command=exit)
self.quit.grid()
if __name__ == '__main__':
root = tki.Tk()
root.title('nesting testing')
outer = tki.LabelFrame(root, text='outer level')
outer.pack()
app = App(outer)
app.pack()
root.mainloop()
Dropping self
in the call to super().__init__()
was one of the first things I tried, but in py2.7 I still got the same error message, whether it was in there or not.
Without self
:
Traceback (most recent call last):
File "C:\Python\TESTS\test_super.py", line 21, in <module>
app = App(outer)
File "C:\Python\TESTS\test_super.py", line 9, in __init__
super(App, self).__init__(master=parent, text='inner') #py 2.7
TypeError: must be type, not classobj
With self
:
Traceback (most recent call last):
File "C:\Python\TESTS\test_super.py", line 21, in <module>
app = App(outer)
File "C:\Python\TESTS\test_super.py", line 8, in __init__
super(App, self).__init__(self, master=parent, text='inner') #py 2.7
TypeError: must be type, not classobj
The fact that the error message stays the same as I drop self suggests that it's not the problem, but the fact it works OK with the BaseClass call is confusing me as to what could be wrong with the other arguments.
Upvotes: 2
Views: 1369
Reputation: 6430
If I remember correct then
super().__init__(self, master=parent, text='inner') #py 3.4
super(App, self).__init__(self, master=parent, text='inner') #py 2.7
should have been -
super().__init__(master=parent, text='inner') #py 3.4
super(App, self).__init__(master=parent, text='inner') #py 2.7
Because you should not pass self
as paramter to __init__
of super.
In fact when using instance methods, you should not pass self
explicitly to any method, self
is automatically provided when the call is made by the interpreter
BTW,
tki.LabelFrame.__init__(self, master=parent, text='inner')
super().__init__(self, master=parent, text='inner') #py 3.4
super(App, self).__init__(self, master=parent, text='inner') #py 2.7
super(App, self).__init__(master=parent, text='inner') #py 2.7
All these calls are redundant. You should use only one of them. I would prefer -
super().__init__(master=parent, text='inner') #py 3.4
or
super(App, self).__init__(master=parent, text='inner') #py 2.7
but if you prefer to use the first one -
tki.LabelFrame.__init__(self, master=parent, text='inner')
make sure you remove the self and make it -
tki.LabelFrame.__init__(master=parent, text='inner')
Upvotes: 2
Reputation: 251353
When using super
in this way, you don't pass self
explicitly. Just do super(App, self).__init__(master=parent, text='inner')
(or super().__init__(master=parent, text='inner')
for Python 3).
Upvotes: 1