Lambdas and variables
James Henderson
james at logicalprogression.net
Tue Jul 27 20:32:42 EDT 2004
John Fouhy wrote:
> So I'm trying to generate Tkinter callback functions on the fly, but
> it's not working, and I don't understand what's going on.
>
> Here is an example program:
>
> --------------------------
> from Tkinter import *
>
> def printSomething(x):
> print x
>
> tk = Tk()
> stuff = ['foo', 'bar', 'baz', 'zif', 'zaf', 'zof']
>
> for x in stuff:
> l = Label(tk, text=x)
> l.pack()
> l.bind('<Enter>', lambda e: printSomething(x))
>
> tk.mainloop()
> --------------------------
>
> The desired behaviour is that the program should print to stdout the
> text on the label whenever the mouse enters that widget.
>
> However, what actually happens is that it prints out 'zof' whenever
> the mouse enters any of the widgets.
>
> To further confuse me, if I add a bit of indirection:
>
> --------------------------
> from Tkinter import *
>
> def makeFunction(x):
> return lambda e: printSomething(x)
>
> def printSomething(x):
> print x
>
> tk = Tk()
> stuff = ['foo', 'bar', 'baz', 'zif', 'zaf', 'zof']
>
> for x in stuff:
> l = Lable(tk, text=x)
> l.pack()
> l.bind('<Enter>', makeFunction(x))
>
> tk.mainloop()
> --------------------------
>
> ...then everything works as it should.
>
> I am running Python 2.3.4.
>
> Can anyone explain this to me?
Derek has answered your question, but you might also be interested to
know that your first example would work with one small change:
for x in stuff:
l = Label(tk, text=x)
l.pack()
l.bind('<Enter>', lambda e, x=x: printSomething(x))
That is, "x" is passed as a default parameter to the lambda, which is
slightly more concise that your defining of an extra function. This
works because default parameters are evaluated once and for all at the
time of a function's definition.
James
More information about the Python-list
mailing list