【问题标题】:Why can't you call object attributes within __init__?为什么不能在 __init__ 中调用对象属性?
【发布时间】:2020-02-08 17:14:47
【问题描述】:

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

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

【问题讨论】:

  • framepanel2 到底是什么? cmets 说panel2 is not callable,为什么你认为它与你的Panel1 构造函数有关?我的意思是,frame 作为该构造函数的参数给出,panel2 是该参数的属性,这意味着您的问题与您的类无关。请详细说明,现在有更多的代码和信息没有意义。
  • 始终共享整个错误消息。变量和函数名称通常应遵循lower_case_with_underscores 样式。标题中问题的答案是,当然可以。
  • 您能否提供一个最小示例来说明您不理解的内容?您的描述暗示了一个带有初始化程序的类,并且大约一两个属性就足够了。

标签: python constructor wxpython


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2020-06-23
    • 2018-05-22
    • 1970-01-01
    • 2010-11-20
    • 2012-05-28
    • 2014-09-22
    • 2020-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多