473,378 Members | 1,617 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Lambdas and variables

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?

--
John.
Jul 18 '05 #1
6 1575
On 27 Jul 2004 16:35:39 -0700, John Fouhy <jf****@paradise.net.nz> 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.

[snip examples]

Can anyone explain this to me?


I'll have a go.

It's to do with the environment to which a function, or a lambda, is
bound. "x" in the lambda will always refer to the x defined in the
enclosing scope, and you last left that set to "zof".

The next case with an explicit function makes it all better because
now the printSomething function has a reference to the actual element
you wish to use via it's argument.

Hope that helps!

dt.
Jul 18 '05 #2
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

Jul 18 '05 #3
[original post: http://groups.google.co.nz/groups?hl...ing.google.com
]

Derek Thomson <de***********@gmail.com> wrote in message news:<ma*************************************@pyth on.org>...
It's to do with the environment to which a function, or a lambda, is
bound. "x" in the lambda will always refer to the x defined in the
enclosing scope, and you last left that set to "zof".


Ok, so when I write 'lambda e: printSomething(x)', that creates a
function which, when called, will look up the value of the variable
'x', and then call printSomething on that value. And that value will
be whatever x was last set to. Is that correct?

What if I do 'lambda e: printSomething(copy.deepcopy(x))'? That
creates a function which, when called, will look up the value of 'x',
make a deep copy, and then call printSomething on it?

('cos that doesn't work either)

If what I wrote is correct, then I think I understand now. And I will
use the change James Henderson suggested. But it definitely feels
like a gotcha if I can't replace a function that just does 'return X'
with 'X' itself.

(thanks for your help, guys)

--
John.
Jul 18 '05 #4
John Fouhy wrote:
[original post: http://groups.google.co.nz/groups?hl...ing.google.com
]

Derek Thomson <de***********@gmail.com> wrote in message news:<ma*************************************@pyth on.org>...
It's to do with the environment to which a function, or a lambda, is
bound. "x" in the lambda will always refer to the x defined in the
enclosing scope, and you last left that set to "zof".
Ok, so when I write 'lambda e: printSomething(x)', that creates a
function which, when called, will look up the value of the variable
'x', and then call printSomething on that value. And that value will
be whatever x was last set to. Is that correct?


That's right, and it's an example of "Python's general late-binding
semantics", which came under so much discussion recently with respect to
generator expressions. See:

http://mail.python.org/pipermail/pyt...il/044555.html

and the surrounding threads.
What if I do 'lambda e: printSomething(copy.deepcopy(x))'? That
creates a function which, when called, will look up the value of 'x',
make a deep copy, and then call printSomething on it?

('cos that doesn't work either)
The copying won't be done till the function is called and you will still
get whatever x was last set to in the lexical scope. But I see you're
trying to associate a piece of data with a function - to create a sort
of closure - and that's exactly where the default argument trick comes
in. Default arguments can be used for this effect since they freeze the
value at the time of the function's definition.
If what I wrote is correct, then I think I understand now. And I will
use the change James Henderson suggested. But it definitely feels
like a gotcha if I can't replace a function that just does 'return X'
with 'X' itself.


I agree it's a gotcha. Interestingly you would have been forced to pass
x in as a default argument and avoided your problem until Python
introduced nested scopes in versions 2.1 and 2.2. You may find PEP 227
on statically nested scopes illuminating:

http://www.python.org/peps/pep-0227.html

James

Jul 18 '05 #5

"John Fouhy" <jf****@paradise.net.nz> wrote in message
news:c0**************************@posting.google.c om...
[original post: http://groups.google.co.nz/groups?hl...ing.google.com ]

Derek Thomson <de***********@gmail.com> wrote in message

news:<ma*************************************@pyth on.org>...
It's to do with the environment to which a function, or a lambda, is
bound. "x" in the lambda will always refer to the x defined in the
enclosing scope, and you last left that set to "zof".


Ok, so when I write 'lambda e: printSomething(x)', that creates a
function which, when called, will look up the value of the variable
'x', and then call printSomething on that value. And that value will
be whatever x was last set to. Is that correct?


To the best of my knowledge,

func = lambda <params>: <expression>

is almost exactly equivalent to and an abbreviation for

def func(<params>): return <expression>

(The main difference that I know of is in func.__name__ and the consequent
difference in repr(func). If someone knows of something more of
significance, please tell me.) So, if you understand simple functions, you
can understand lambdas -- without asking ;-).

Terry J. Reedy

Jul 18 '05 #6
James Henderson <ja***@logicalprogression.net> wrote in message news:<ma*************************************@pyth on.org>...
I agree it's a gotcha. Interestingly you would have been forced to pass
x in as a default argument and avoided your problem until Python
introduced nested scopes in versions 2.1 and 2.2. You may find PEP 227
on statically nested scopes illuminating:

http://www.python.org/peps/pep-0227.html


Heh.

""" The proposed
solution, in crude terms, implements the default argument approach
automatically. The "root=root" argument can be omitted. """

Ok, I've got it now (famous last words).

Thanks for your help :-)

--
John.
Jul 18 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: gong | last post by:
hi i would like to pickle a lambda; according to the library docs in 2.3, i believe this shouldnt be possible, since a lambda is not a function defined at the top level of a module (?) ...
2
by: Fernando Perez | last post by:
Hi all, there are a couple of threads on lambdas today, which got me curious about their differences as far as bytecode goes: planck|2> lf=lambda x: x**2 planck|3> def ff(x): return x**2 |.>...
51
by: bearophileHUGS | last post by:
On Slashdot there is a discussion about the future C#3.0: http://developers.slashdot.org/developers/05/09/18/0545217.shtml?tid=109&tid=8 http://msdn.microsoft.com/vcsharp/future/ There are...
5
by: Ross A. Finlayson | last post by:
Hi, I'm scratching together an Access database. The development box is Office 95, the deployment box Office 2003. So anyways I am griping about forms and global variables. Say for example...
7
by: Michael | last post by:
Hi newsgroup, as the subject indicates I am looking for an advice using global variables. I am not if this problem is more about style then C. If its wrong in thi group, sorry. So I have a...
5
by: Sandman | last post by:
I dont think I understand them. I've read the section on scope in the manual inside out. I'm running PHP 5.2.0 Here is the code I'm working on: //include_me.php <?php $MYVAR = array(); global...
5
by: Chris Johnson | last post by:
What I want to do is build an array of lambda functions, like so: a = (This is just a demonstrative dummy array. I don't need better ways to achieve the above functionality.) print ...
1
weaknessforcats
by: weaknessforcats | last post by:
C++: The Case Against Global Variables Summary This article explores the negative ramifications of using global variables. The use of global variables is such a problem that C++ architects have...
29
by: jmDesktop | last post by:
For students 9th - 12th grade, with at least Algebra I. Do you think Python is a good first programming language for someone with zero programming experience? Using Linux and Python for first...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.