Packaging data+function into a Tkinter command

Post here if you need help with creating a Graphical User Interface in Python.

Packaging data+function into a Tkinter command

Postby rovf » Mon Aug 19, 2013 12:16 pm

Here is a simplified version of my first attempt of this kind of code - it works, but it is not written well:

Code: Select all
  # somewhere in my class ....
  def setup(self):
    ....
    self.button_start[0]=Button(top_chooser,text=self.S.start_button_text(0),command=self.start_0)
    self.button_start[1]=Button(top_chooser,text=self.S.start_button_text(1),command=self.start_1)
    self.button_start[2]=Button(top_chooser,text=self.S.start_button_text(2),command=self.start_2)
    self.button_start[3]=Button(top_chooser,text=self.S.start_button_text(3),command=self.start_3)
    for i in range(0,4):
      self.button_start[i].pack()
       
  ....
     
  def self.start_0(self):
    self.start(0)

  def self.start_1(self):
    self.start(1)

  def self.start_2(self):
    self.start(2)

  def self.start_3(self):
    self.start(3)

  def start(self,kind):
    .....


The four buttons behave nearly identical. It's only that the command will be invoked with a different index number. It alll should be implementable within a loop, if it were not for passing the index number to a command. Bad programming style.

Now a command doesn't need to be a function. It could also be a callable object, so one solution would be to make a tiny class which wraps a reference to self, the index number, and the start function, and calls it. Much better, but it seems to me like overkill.

If I only would have currying in Python, something like
command=self.start(i)

Is there a neat solution to this problem? Ideally one which also works in 2.3.5...
rovf
 
Posts: 25
Joined: Fri Aug 16, 2013 4:35 pm

Re: Packaging data+function into a Tkinter command

Postby stranac » Mon Aug 19, 2013 1:23 pm

You have two choices:
  • functools.partial() - as close as it gets to currying in python, but I'm not sure if it's available in 2.3.5(that's ancient, why are you still using it?)
    Code: Select all
    command=functools.partial(self.start, 0)
  • lambda functions
    Code: Select all
    command=lambda: self.start(0)
Friendship is magic!

R.I.P. Tracy M. You will be missed.
User avatar
stranac
 
Posts: 1115
Joined: Thu Feb 07, 2013 3:42 pm

Re: Packaging data+function into a Tkinter command

Postby rovf » Sat Aug 24, 2013 8:50 am

stranac wrote:You have two choices:
  • functools.partial() - as close as it gets to currying in python, but I'm not sure if it's available in 2.3.5(that's ancient, why are you still using it?)

From the information I collected on the Net, this is the most recent version which safely runs on Mac OSX 10.4. For my work doing with Jython, I have already 2.5.4 running, but the program I'm doing now, should also run on "plain" Python.
stranac wrote:
  • lambda functions
    Code: Select all
    command=lambda: self.start(0)

  • I think I will use this version. It's at least slightly better than what I have now (I still have to write a separate function for each call, but I don't have to invent names for them).
    It would be better to maintain to write it as a loop, but I think, I would then have to use eval() to construct the curryied functions dynamically....


    Update: I didn't think well enough. Of course I can do it in a loop, WITHOUT relying to eval, since lambda essentially is a closure and captures the variables defined in the surrounding block (and hence the loop variable too). Thanks a lot, I implemented it now in this way, and it seems to work well.
    rovf
     
    Posts: 25
    Joined: Fri Aug 16, 2013 4:35 pm


    Return to GUI

    Who is online

    Users browsing this forum: No registered users and 3 guests