Tkinter.Button(... command) lambda and argument problem

James Stroud jstroud at mbi.ucla.edu
Sat Sep 16 01:23:16 EDT 2006


Dustan wrote:
> Jay wrote:
> 
>>Thanks for the tip, but that breaks things later for what I'm doing.
>>
>>bearophileHUGS at lycos.com wrote:
>>
>>>In that case you don't need a lambda:
>>>
>>>import Tkinter as tk
>>>
>>>class Test:
>>>    def __init__(self, parent):
>>>        buttons = [tk.Button(parent, text=str(x+1),
>>>command=self.highlight(x)) for x in range(5)]
>>>        for button in buttons:
>>>            button.pack(side=tk.LEFT)
> 
> 
> Well, actually, that's wrong. You obviously don't understand why lambda
> is necessary for event binding; in this case (and many others, for that
> matter), the button gets bound to the event *returned* by
> self.highlight(x), which, since nothing gets returned, would be None.
> Then when you click the button, Tkinter calls None(), and out of the
> blue, an error is raised.
> 
> Lambda is the safe way around that error.
> 
> 
>>>    def highlight(self, x):
>>>        print "highlight", x
>>>
>>>root = tk.Tk()
>>>d = Test(root)
>>>root.mainloop()
>>>
>>>Bye,
>>>bearophile
> 
> 

Actually, lambda is not necessary for event binding, but a closure (if I 
have the vocab correct), is:

import Tkinter as tk

def make_it(x):
   def highliter(x=x):
     print "highlight", x
   return highliter

class Test:
     def __init__(self, parent):
         buttons = [tk.Button(parent, text=str(x+1),
                    command=make_it(x)) for x in range(5)]
         for button in buttons:
             button.pack(side=tk.LEFT)

root = tk.Tk()
d = Test(root)
root.mainloop()


-- 
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/



More information about the Python-list mailing list