Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #55642 > unrolled thread
| Started by | Rotwang <sg552@hotmail.co.uk> |
|---|---|
| First post | 2011-02-11 04:54 +0000 |
| Last post | 2011-02-11 05:26 +0000 |
| Articles | 6 — 5 participants |
Back to article view | Back to comp.lang.python
Parameterized functions of no arguments? Rotwang <sg552@hotmail.co.uk> - 2011-02-11 04:54 +0000
Re: Parameterized functions of no arguments? Hrvoje Niksic <hniksic@xemacs.org> - 2011-02-11 15:43 +0100
Re: Parameterized functions of no arguments? Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2011-02-10 23:22 -0800
Re: Parameterized functions of no arguments? Carl Banks <pavlovevidence@gmail.com> - 2011-02-11 05:59 +0000
Re: Parameterized functions of no arguments? Chris Rebert <clp2@rebertia.com> - 2011-02-10 21:50 -0800
Re: Parameterized functions of no arguments? Rotwang <sg552@hotmail.co.uk> - 2011-02-11 05:26 +0000
| From | Rotwang <sg552@hotmail.co.uk> |
|---|---|
| Date | 2011-02-11 04:54 +0000 |
| Subject | Parameterized functions of no arguments? |
| Message-ID | <ij2fdr$uo7$1@news.eternal-september.org> |
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?
[toc] | [next] | [standalone]
| From | Hrvoje Niksic <hniksic@xemacs.org> |
|---|---|
| Date | 2011-02-11 15:43 +0100 |
| Message-ID | <87bp2izl6a.fsf@xemacs.org> |
| In reply to | #55642 |
Chris Rebert <clp2@rebertia.com> writes: > It's a well-known problem due to the intricacies of Python's scoping > rules. Actually, it is not specific to Python's scoping rules (which mandate local, then module-level, then built-in name lookup). The root of the surprise is, as you correctly point out, the fact that the variable's "cell" is shared by all iterations through the loop. Taking that into account, it logically follows that all enclosed functions end up reading the same value. This is not endemic to Python, the exact same surprise is present in Common Lisp, a language with long tradition of closures and otherwise radically different scoping rules. * (setq l (loop for i from 1 to 10 collect (lambda () i))) * (mapcar #'funcall l) (11 11 11 11 11 11 11 11 11 11)
[toc] | [prev] | [next] | [standalone]
| From | Dennis Lee Bieber <wlfraed@ix.netcom.com> |
|---|---|
| Date | 2011-02-10 23:22 -0800 |
| Message-ID | <mailman.93.1297408937.1633.python-list@python.org> |
| In reply to | #55642 |
On Fri, 11 Feb 2011 04:54:11 +0000, Rotwang <sg552@hotmail.co.uk>
declaimed the following in gmane.comp.python.general:
> menu.add_command(label = str(k), command = lambda: f(k))
>
I'm not sure, but what effect does
menu.add_command(label=str(k), command = lambda k=k: f(k))
have on the processing.
Confusing syntax, I know... does it make more sense as
... lambda x=k: f(x)...
--
Wulfraed Dennis Lee Bieber AF6VN
wlfraed@ix.netcom.com HTTP://wlfraed.home.netcom.com/
[toc] | [prev] | [next] | [standalone]
| From | Carl Banks <pavlovevidence@gmail.com> |
|---|---|
| Date | 2011-02-11 05:59 +0000 |
| Message-ID | <ij2j82$a8u$1@news.eternal-september.org> |
| In reply to | #55642 |
Rotwang wrote:
> On 11/02/2011 04:54, Rotwang wrote:
> Mmmmnngh, that obviously wasn't going to work. Here's something that
> does work:
>
> menu = Tkinter.Menu(master, tearoff = 0)
> for k in x:
> def f(j = k):
> [do something that depends on j]
> menu.add_command(label = str(k), command = f)
>
> Still, I'd like to know if there's a more elegant method for creating a
> set of functions indexed by an arbitrary list.
If you don't want to use keyword arguments you can define a helper
function to help create your closure:
def create_menu_command(j):
def f():
do_something_that_depends_on(j)
return f
for k in x:
menu.add_command(label=str(k),command=create_menu_command(k))
Carl Banks
[toc] | [prev] | [next] | [standalone]
| From | Chris Rebert <clp2@rebertia.com> |
|---|---|
| Date | 2011-02-10 21:50 -0800 |
| Message-ID | <mailman.91.1297403413.1633.python-list@python.org> |
| In reply to | #55642 |
On Thu, Feb 10, 2011 at 8:54 PM, Rotwang <sg552@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
[toc] | [prev] | [next] | [standalone]
| From | Rotwang <sg552@hotmail.co.uk> |
|---|---|
| Date | 2011-02-11 05:26 +0000 |
| Message-ID | <ij2ha2$kss$1@news.eternal-september.org> |
| In reply to | #55642 |
On 11/02/2011 04:54, Rotwang 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)
Mmmmnngh, that obviously wasn't going to work. Here's something that
does work:
menu = Tkinter.Menu(master, tearoff = 0)
for k in x:
def f(j = k):
[do something that depends on j]
menu.add_command(label = str(k), command = f)
Still, I'd like to know if there's a more elegant method for creating a
set of functions indexed by an arbitrary list.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web