繁体   English   中英

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

[英]Why can't you call object attributes within __init__?

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

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))

有人可以给我一个链接来解释为什么在构造函数中这是不可能的吗?

谢谢!

*****编辑****

以下是有助于更好地解释我的问题的功能代码。 如果您尝试通过 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()

以下是有助于更好地解释我的问题的功能代码。 如果您尝试通过 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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM