为什么不能在__init__中调用对象属性?

问题描述 投票:-1回答:1

我试图理解为什么您可以在类的方法中而不是在其构造函数中调用对象的属性。例如:

class Panel1(wx.Panel):

    #include Frame in the constructor
    def __init__(self, parent, frame):
        wx.Panel.__init__(self, parent)
        #set up so objects assigned in Frame (and it's children) can be called
        self.frame = frame
        button = wx.Button(self, label='Test')
        #button.Bind(wx.EVT_BUTTON, lambda event: self.onButton(event))
        button.Bind(wx.EVT_BUTTON, self.onButton)

        pprint(vars(self.frame))


    def onButton(self, event):
        print("Button pressed.")
        pprint(vars(self.frame))
        #the following fails in the constructor as panel2 for some reason is not callable
        a = self.frame.panel2.a
        print("123: " + str(a))

有人可以指出指向我的链接,该链接解释了为什么在构造函数中无法做到这一点?

谢谢!

***** EDIT ****

下面是功能代码,可以帮助更好地解释我的问题。如果尝试通过Panel1的构造函数中的父级调用Panel2属性,它将失败。但是,在Panel1的onButton方法中完成此操作后,效果很好。我想了解原因。

import wx
from pprint import pprint

class Panel1(wx.Panel):

    #include Frame in the constructor
    def __init__(self, parent, frame):
        wx.Panel.__init__(self, parent)

        self.frame = frame
        self.strPanel1 = "Panel1 string"
        self.intPanel1 = 0

        button = wx.Button(self, label='Test')
        button.Bind(wx.EVT_BUTTON, self.onButton)

        self.textbox = wx.TextCtrl(self)

        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)
        sizer.Add(self.textbox, 0, wx.ALL, 5)
        sizer.Add(button, 0, wx.ALL, 5)
        #pprint self.frame attributes fail here

    def onButton(self, event):
        #but not here!?!
        print("Panel1 button pressed.")
        pprint(vars(self.frame))
        Panel2str = self.frame.panel2.strPanel2
        print(Panel2str)
        Panel2int = self.frame.panel2.intPanel2
        print(str(Panel2int))
        #Panel2 button press counter
        self.frame.panel2.intPanel2 += 1
        self.frame.panel2.trigger()

    def trigger(self):
        print("Panel1 has been triggered")

class Panel2(wx.Panel):

    #include Frame in the constructor
    def __init__(self, parent, frame):
        wx.Panel.__init__(self, parent)

        self.frame = frame
        self.strPanel2 = "Panel2 string"
        self.intPanel2 = 0

        button = wx.Button(self, label='Test')
        button.Bind(wx.EVT_BUTTON, self.onButton)

        self.textbox = wx.TextCtrl(self)

        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)
        sizer.Add(self.textbox, 0, wx.ALL, 5)
        sizer.Add(button, 0, wx.ALL, 5)
        #pprint self.frame attributes fail here

    def onButton(self, event):
        #but not here!?!
        print("Panel2 button pressed.")
        pprint(vars(self.frame))
        Panel1str = self.frame.panel1.strPanel1
        print(Panel1str)
        Panel1int = self.frame.panel1.intPanel1
        print(str(Panel1int))
        #Panel1 button press counter
        self.frame.panel1.intPanel1 += 1
        self.frame.panel1.trigger()

    def trigger(self):
        print("Panel2 has been triggered")

class Frame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, title="My Frame")

        #Spliiting the frame
        splitter = wx.SplitterWindow(self)

        #Send frame to children
        self.panel1 = Panel1(splitter, self)
        self.panel2 = Panel2(splitter, self) 

        splitter.SplitVertically(self.panel1, self.panel2, 0)
        splitter.SetMinimumPaneSize(200)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(splitter, 1, wx.EXPAND)

        self.SetSizer(sizer)


if __name__ == '__main__':
    app = wx.App()
    frame = Frame()
    frame.Show()
    frame.Centre()
    app.MainLoop()
python constructor wxpython
1个回答
0
投票

下面是功能代码,可以帮助更好地解释我的问题。如果尝试通过Panel1的构造函数中的父级调用Panel2属性,它将失败。

失败,因为在调用您的Panel1.__init__时,尚未设置frame.panel2。查看您的Frame类:

class Frame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, title="My Frame")

        #Spliiting the frame
        splitter = wx.SplitterWindow(self)

        #Send frame to children
        self.panel1 = Panel1(splitter, self)
        self.panel2 = Panel2(splitter, self)

        ...

初始化Panel1时,尚未设置panel2。仅在完成Panel1的初始化并将其分配给frame.panel1时设置。如果您绝对需要将panel2访问到Panel1.__init__中,则可以这样做,以便Panel1来处理它。例如:

class Panel1:
    def __init__(self, frame):
        # Initialize panel2 and assign it to our frame
        frame.panel2 = Panel2(frame)

        # Now we can do whatever with panel2
        frame.panel2

class Panel2:
    def __init__(self, frame):
        pass

class Frame:
    def __init__(self):
        # This initialize panel1, and internally initialize panel2
        self.panel1 = Panel1(self)


frame = Frame()
© www.soinside.com 2019 - 2024. All rights reserved.