Question 1: Why do I have to call super().__init__()
This is a pared down example:
mport wx
class MyFrame(wx.Frame):
pass
print(*MyFrame.__mro__, sep="\n")
Run this code and it prints the Method Resolution Order, the class path that is followed when looking for attributes or calling methods. This is what gets printed.
Output:
<class '__main__.MyFrame'>
<class 'wx._core.Frame'>
<class 'wx._core.TopLevelWindow'>
<class 'wx._core.NonOwnedWindow'>
<class 'wx._core.Window'>
<class 'wx._core.WindowBase'>
<class 'wx._core.EvtHandler'>
<class 'wx._core.Object'>
<class 'wx._core.Trackable'>
<class 'sip.wrapper'>
<class 'sip.simplewrapper'>
<class 'object'>
Calling super().__init__() in the MyFrame.__init__() method calls wx._core.Frame.__init__(). That method in turn likely calls wx._core.TopLevelWindow.__init__() which probably calls wx._core.NonOwnedWindow, and so on and so on. All those method probably perform some important steps in initializing a Frame object. If you didn't call super().__init__(), none of that code would be executed.
Question 2: When should I pass an argument when I create an object.
When it is needed.
I'm going to rewrite your code to make the following discussion a bit less confusing.
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(None, title='Hello World')
parent_frame= self
MyPanel(parent_frame)
self.Show()
When MyFrame.__init__() calls MyPanel(parent_frame) it does two things. It creates a new MyPanel object, and it calls MyPanel.__init__(parent_frame)
In MyPanel.__init__(self, parent), self is the new MyPanel object, and parent is the parent_frame argument. The first argument of an instance method is the instance of the object that provides the context for the method. By convention this is always called "self". Arguments passed when the object was created appear after self.
So how do you know when you need to pass arguments to the __init__() method? You look at the code or your read the documentation. You wrote MyFrame, so you can look at your code and see if you need to pass any arguments.
class MyPanel(wx.Panel):
def __init__(self, parent):
You can clearly see that parent is a required argument, so any time you create a MyPanel object you need to pass an argument for parent.
But what about here?
class MyFrame(wx.Frame):
def __init__(self):
#RuntimeError: super-class __init__() of type MyFrame was never called
super().__init__(None, title='Hello World')
There are no arguments following self in MyFrame.__init__(self), so you cannot pass an argument.
You could rewrite your code like this:
class MyFrame(wx.Frame):
def __init__(self, parent=None):
#RuntimeError: super-class __init__() of type MyFrame was never called
super().__init__(parent, title='Hello World')
Now you have the option of passing a "parent" argument when you create a MyFrame. What does the parent argument do? That is where you need to look at the documentation.
https://docs.wxpython.org/wx.Frame.html
Quote:__init__ (self, parent, id=ID_ANY, title=””, pos=DefaultPosition, size=DefaultSize, style=DEFAULT_FRAME_STYLE, name=FrameNameStr)
Constructor, creating the window.
Parameters:
parent (wx.Window) – The window parent. This may be, and often is, None. If it is not None, the frame will be minimized when its parent is minimized and restored when it is restored (although it will still be possible to minimize and restore just this frame itself).
For a Frame, the parent is an optional argument If provided, the child frame is minimized and restored when the parent is minimized and restored.