On Thu, Feb 10, 2011 at 8:54 PM, Rotwang <sg...@hotmail.co.uk> wrote: > Hi all > > Sorry if this is a dumb question, I would guess it's answered in an FAQ > somewhere but I haven't been able to find anything that helps. I'm trying to > use Tkinter to create a menu whose entries and corresponding commands depend > on some list x. I want the menu options to be labelled by the elements of x, > and upon selecting an option k I want my program to execute a function f(k). > So I tried writing something that schematically looked like this: > > def f(k): > [do something that depends on k] > > menu = Tkinter.Menu(master, tearoff = 0) > for k in x: > menu.add_command(label = str(k), command = lambda: f(k)) > > The trouble is, whenever I open the menu and click on any entry k, instead > of evaluating f(k) it always evaluates f(x[-1]). I've also tried this: > > menu = Tkinter.Menu(master, tearoff = 0) > for k in x: > def f(): > [do something that depends on k] > menu.add_command(label = str(k), command = f) > > and it gives me the same problem. Can anybody suggest a way around this?
It's a well-known problem due to the intricacies of Python's scoping rules. One workaround is: for k in x: def f(k=k): [rest same as before] Basically, the problem is that f() does close over the variable k, but not the particular value of k at the time it was defined; f() looks up the value of k anew each time it's called. But by the time you get around to actually calling f(), the loop has terminated and thus k retains its last value of x[-1]. Default argument values, however, are evaluated only once and at definition-time, thus achieving the intended behavior. Cheers, Chris -- http://blog.rebertia.com -- http://mail.python.org/mailman/listinfo/python-list