Tim Daneliuk <[EMAIL PROTECTED]> wrote: > I am trying to initialize a menu in the following manner: > > for entry in [("Up", KeyUpDir), ("Back", KeyBackDir), ("Home", > KeyHomeDir), ("Startdir", KeyStartDir), ("Root", KeyRootDir)]: > > func = entry[1] > UI.ShortBtn.menu.add_command(label=entry[0], command=lambda: func(None)) > > However, at runtime, each of the menu options binds to the *last* function > named in the list (KeyStartDir). > > Explicitly loading each entry on its own line works fine: > > UI........command=lambda:KeyWHATEVERDir(None) > > Any ideas why the first form does not fly?
One word: late binding. Well, two, pedantically speaking;-). The lambda you're passing as the value for 'command' is a closure: it knows it will have to look up name 'func' in the environment in which it's embedded -- but also that it's meant to do that lookup as late as possible, each time it's called. If you wanted to do the lookup just once, at the time lambda executes and created an anonymous function rather than each time said anonymous function is called, you could have expressed that...: command=lambda func=func: func(None) Here, func is a local variable (argument) of the anonymous function, and its "default value" is set ONCE, when the anon function is created. Back to your code, when your anon function is called, it looks up name 'func' in the surrounding environment... and there it finds it bound to whatever it was RE-bound to the LAST time... Point to remember: a closure looks up free-variable names in its surrounding environment *as late as possible*, i.e., when the function object is called; while default argument values are evaluated *at function creation time* (when lambda or def executes, not when the resulting function object gets called). Alex -- http://mail.python.org/mailman/listinfo/python-list