Tkinter Menu command

Alex Martelli aleax at aleax.it
Sat Jul 13 12:18:37 EDT 2002


Raimo Tuisku wrote:

> Is it possible to pass arguments to a method which is executed after
> event? I am trying to do so with add_command method from Menu widget to
> avoid writing separate method for every case.

I proposed what I personally consider the most elegant solution just 
a few days ago, I think.  In your context, add (assuming Python 2.2,
which you seem to have judging from your later observation):

      def makeColorSetter(self, color):
          def setcolor(): self.label.config(fg=color)
          return setcolor

> #From class App:
>     self.mb = Menubutton(self.frame, text="Color")
>     self.mb.grid()
>     self.mb.menu = Menu(self.mb,tearoff=0)
>     self.mb['menu'] = self.mb.menu
>     self.colors=['red','green','blue']
>     for item in self.colors:
>         self.mb.menu.add_command

change to:

          self.mb.menu.add_command(label=item,
              command=self.makeColorSetter(item))
       
>         (label=item,command=lambda :self.set_color(item))
>     # Even this doesn't work. Apparently it always uses
>     # self.set_color('blue'). (self.label colors to blue)

Yes, you need to take a "snapshot", which requires item
be passed as an argument -- if you access the outer function
value of variabie 'item', you'll always get the most recent
value at the time your function run, not the value at the
time the function was created.

So basically you'd need:
    command=lambda color=item: self.set_color(color)

Personally, I find lambda most often results in less-readable
code, even if you assume the code reader or maintainer is fully
informed regarding such refinements as 'snapshot behavior'
versus 'nested scopes'.

My advice is to choose a "closure" idiom, i.e., a function
(or method) that contains and returns another function, like
the 'makeColorSetter' in this case.  This gives you the
generally-needed 'snapshot' effect automatically, and lets
you give names to the two functions involved, which, assuming
you choose such names well, enhances code clarity.


Alex




More information about the Python-list mailing list