title: Passing variable from one class instance to another using Python?
body: <p>I'm having trouble passing a variable defined in one class instance to another class instance. I am relatively new to using classes, but it is my understanding that variables can be passed from one instance to another by simply defining as part of the class instance (such as in the following example). While I've used this model in the past I've never attempted to do this using a GUI framework such as <code>wxPython</code>.</p>
  
  <pre><code>class Foo(object):
      def __init__(self, var):
          self.var = var
  
  class Bar(object):
      def do_something(self, var):
          print var*3
  
  if __name__ == '__main__':
      f = Foo(3)
      b = Bar()
      b.do_something(f.var)
  </code></pre>
  
  <p>The problem I'm having is that the wxPython instance seems to be predefined and will not accept any additional parameters (allowing me to only pass things like title, size, etc.) to the class instance. </p>
  
  <p>The other issue I'm facing is I'm attempting to pass the variable three classes deep by calling a dialog window, and from the dialog I call a separate class designed to start a worker thread. </p>
  
  <p>So my questions are: </p>
  
  <ol>
  <li><p><strong>How can I pass the variable from the first class instance to the third class instance?</strong></p></li>
  <li><p><strong>How can I override the wxPython instance to allow for the definition of additional variables?</strong></p></li>
  <li><p><strong>OR, Could it be possible to create a custom event handler to pass the necessary data?</strong> </p></li>
  </ol>
  
  <p>To clarify...</p>
  
  <p>I'm using Python and would like to think that I understand the fundamentals of programming using Classes and a GUI with frameworks such as Tkinter and wxPython (used in this project). I've written a main class/instance that gets some data from the user and I would like to be able to pass the information stored in self.main_instance_var and pass it along to a second class/instance (in this case a Progress Dialog window called from the first class. </p>
  
  <p>When I attempted to use the above model in my Progress Dialog I got a very uninformative syntax error ('non-keyword arg after keyword arg'). Preventing me from further passing the variable from the Progress Dialog window on to the worker thread. If I had gotten an exception that would have been one thing but the syntax error I don't understand. Look below for a short example:</p>
  
  <pre><code>class ProgressDialog(wx.Dialog):
  
      def __init__(self, parent, title, myVar):     # Generates syntax error on this line
          super(ProgressDialog, self).__init__(parent=parent, 
              title=title, size=(500, 110))
          self.var = myVar
  </code></pre>
  
  <p>Basic Source (by request, sorry its so dirty):</p>
  
  <pre><code>import time
  import os, sys, wx
  from ftplib import FTP_TLS
  
  from threading import Thread
  from wx.lib.pubsub import Publisher
  
  ########################################################################
  class FtpValues(object):
      """ Returns a property attribute - called by FtpFileTransfer
      Used to set values/variables for Host, USERID, PASSWD, FILE """
  
      #----------------------------------------------------------------------
      def __init__(self):
          self.varList = None
  
      #----------------------------------------------------------------------    
      def GetValues(self):
          return self.varList
  
      #----------------------------------------------------------------------
      def SetValues(self, HOST, USERID, PASSWD, FILE):
          self.varList = [HOST, USERID, PASSWD, FILE]
  
      #----------------------------------------------------------------------
      def DelValues(self):
          del self.valList
  
      Values = property(GetValues, SetValues, DelValues, "Set/Get FtpValues")
  
      # http://docs.python.org/library/functions.html#property
  
  ########################################################################
  class FtpFileTransfer(Thread):
      """Test Worker Thread Class."""
  
      #----------------------------------------------------------------------
      def __init__(self):
          """Init Worker Thread Class."""
          Thread.__init__(self)
          self.StartTransfer()        # start the thread
  
      #----------------------------------------------------------------------
      def StartTransfer(self):        # was named run - started automatically                                    
          """Run Worker Thread."""    # when called by the start method
          # This is the code executing in the new thread.
  
          HOST, USERID, PASSWD, FILE = FtpValues.Values
          BLOCKSIZE = 57344
          try:
              ftp = FTP_TLS(HOST)
              ftp.login(USERID, PASSWD)
              ftp.prot_p()
              ftp.voidcmd("TYPE I")
              f = open(FILE, 'rb')
              datasock, esize = ftp.ntransfercmd(
                      'STOR %s' % os.path.basename(FILE))
              size = os.stat(FILE)[6]
              bytes_so_far = 0
              while 1:
                  buf = f.read(BLOCKSIZE)
                  if not buf:
                      break
                  datasock.sendall(buf)
                  bytes_so_far += len(buf)
                  msg = [bytes_so_far, size]
                  Publisher().sendMessage("update", msg)
          except: raise
          finally:
              try:
                  datasock.close()
                  f.close()
                  ftp.voidresp()
                  ftp.quit()
                  print 'Complete...'
              except: pass
  
          wx.CallAfter(Publisher().sendMessage, "update", "Database Transfer Complete!")
  
  
  ########################################################################
  class ProgressDialog(wx.Dialog):
  
      def __init__(self, parent, title):
          super(ProgressDialog, self).__init__(parent=parent, 
              title=title, size=(500, 110))
  
          self.displayLbl = wx.StaticText(self, -1, 'Verifying Database Files... ', (20, 20)) #Preparing for Transfer...
          self.gauge = wx.Gauge(self, -1, 100, (20, 45), (370, 24))        
          self.btn = btn = wx.Button(self, -1, 'Cancel', (400, 45), (-1, 25))
          btn.Bind(wx.EVT_BUTTON, self.OnClose)
  
          # listens for response from worker thread
          Publisher().subscribe(self.updateDisplay, "update")
  
          FtpFileTransfer()#.StartTransfer(HOST, USERID, PASSWD, FILE)        #Start the FTP Worker Thread
          #self.OnStart()
  
      #----------------------------------------------------------------------
      def run(self):
          FtpFileTransfer(HOST, USERID, PASSWD, FILE)
  
      #----------------------------------------------------------------------
      def OnClose(self, event):
          """ Place Holder """
          if self.btn.GetLabel() == 'Finish':
              # Do Something!
              pass
          return None
  
      #----------------------------------------------------------------------
      def updateDisplay(self, msg):
          """ Receives data from thread and updates the display """
          if isinstance(msg.data, list):
              bytes_so_far, size = msg.data
              k = 100 * bytes_so_far / size
              self.displayLbl.SetLabel("Sent %d of %d bytes %.1f%%" % (bytes_so_far, size, 100 * bytes_so_far / size))
              self.gauge.SetValue(k)
          else:
              self.displayLbl.SetLabel("%s" % msg.data)
              #self.btn.Enable()
              self.btn.SetLabel('Finish')
  
  
  ########################################################################
  class MyForm(wx.Frame):
  
      #----------------------------------------------------------------------
      def __init__(self):
          wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial")
  
          # Add a panel so it looks the correct on all platforms
          panel = wx.Panel(self, wx.ID_ANY)
          self.displayLbl = wx.StaticText(panel, label="Amount of time since thread started goes here")
          self.btn = btn = wx.Button(panel, label="Start Thread")
          self.gauge = wx.Gauge(panel, -1, 100, size=(370, 24))
  
          btn.Bind(wx.EVT_BUTTON, self.onButton)
  
          sizer = wx.BoxSizer(wx.VERTICAL)
          sizer.Add(self.displayLbl, 0, wx.ALL|wx.CENTER, 5)
          sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
          sizer.Add(self.gauge, 0, wx.ALL|wx.CENTER, 5)
          panel.SetSizer(sizer)
  
          self.VarData()
          # create a pubsub receiver
          Publisher().subscribe(self.updateDisplay, "update")
  
      #----------------------------------------------------------------------
      def onButton(self, event):
          """
          Runs the thread
          """
  
          chgdep = ProgressDialog(None, title='File Transfer. . .')
          chgdep.ShowModal()
          #chgdep.Destroy()
  
      #----------------------------------------------------------------------
      def updateDisplay(self, msg):
          """
          Receives data from thread and updates the display
          """
          if isinstance(msg.data, list):
              bytes_so_far, size = msg.data
              k = 100 * bytes_so_far / size
              self.displayLbl.SetLabel("Sent %d of %d bytes %.1f%%" % (bytes_so_far, size, 100 * bytes_so_far / size))
              self.gauge.SetValue(k)
          else:
              self.displayLbl.SetLabel("%s" % msg.data)
              self.btn.Enable()
  
      #----------------------------------------------------------------------
      def VarData(self):
          HOST = '127.0.0.1'
          USERID = 'test'
          PASSWD = 'P@ssw0rd'
          FILE = r'F:\Programming\temp\Test.zip'
          varList = [HOST, USERID, PASSWD, FILE]
          FtpValues.Values = HOST, USERID, PASSWD, FILE
  
  #----------------------------------------------------------------------
  # Run the program
  if __name__ == "__main__":
      app = wx.PySimpleApp()
      frame = MyForm().Show()
      app.MainLoop()
  </code></pre>