scoping weirdness
Paul Rubin
phr-n2001 at nightsong.com
Sat Aug 25 04:35:19 EDT 2001
"Tim Peters" <tim.one at home.com> writes:
> Of course. Try the same thing in Scheme (which you've already confessed to
> knowing <wink>):
>
> (define (foo n)
> (let ((a (lambda () n)))
> (set! n (+ n 3))
> a))
>
> (define x (foo 1))
>
> After that, (x) evaluates to 4 too.
Well ok, but I thought we had a thread the other day saying Python
doesn't actually have closures :-). Anyway I was surprised.
> Most Python programmers would write a class, though, explicitly binding an
> instance variable to the value they wanted at the time they wanted to
> capture it. Like: (example snipped to save space)...
>
> It's a bit more typing at the start, but more flexible in the end, because
> the state is materialized explicitly (and so open to fiddling via writing
> new methods as requirements change), rather than implicitly hidden away in
> closures.
Yes, let me go up a level and ask if there's a better way to do this.
It's for Tkinter--say I want several buttons that all call the same
function, giving the button text as an argument. My code looks
something like:
from __future__ import nested_scopes
from Tkinter import *
def press_button (text):
print 'you pressed %s' % text
def create_button (label):
func = lambda: press_button (label)
Button(root,text=label,command=func).pack()
# if I put more stuff here and set label to something new,
# the button doesn't do what I expected.
root = Tk()
create_button ("fear")
create_button ("surprise")
create_button ("ruthless efficiency")
The point is that from the Tkinter docs it looks like the Button
widget really wants its command parameter to be a function with no
args, so I needed to create a lambda that would call press_button with
the arg I wanted.
What would be best is if the Button widget had a way of passing args
to its command func. Is there something like that which I missed?
Thanks as usual.
More information about the Python-list
mailing list