lambda closure question

Carl Banks invalidemail at aerojockey.com
Sat Feb 19 03:43:33 EST 2005


Ted Lilley wrote:
> What I want to do is pre-load functions with arguments by iterating
> through a list like so:
>
> >>>class myclass:
> ...    pass
> >>>def func(self, arg):
> ...    print arg
> >>>mylist = ["my", "sample", "list"]
> >>>for item in mylist:
> ...    setattr(myclass, item, lamdba self: func(self, item))

[snip]

> Unfortunately, it doesn't work.  It seems the closure keeps track of
> the variable fed to it dynamically - if the variable changes after
the
> lambda is created, the lambda still references the _variable_ not the
> original _value_ and so gets the new value like so:
>
> >>>obj.sample()
> list
> >>>obj.my()
> list
>
> At least, that's the explanation I'm deducing from this behavior.

And that's the correct explanation, chief.


> Assuming that's the way Guido intended it to be (about as dynamic as
it
> can get), I'm at a loss to do what _I_ want it to do.  In fact, I
don't
> think there's any way to generate the lambdas properly without coding
> in the name as a literal string, since any attempt to use a variable
> reference will always get modified as the loop iterates.

It is intended that way.  As an example of why that is: consider a
nested function called "printvars()" that you could insert in various
places within a function to print out the value of some local variable.
 If you did that, you wouldn't want printvars to print the values at
the time it was bound, would you?

Anyways, this can be worked around, but I'd suppose it's not as
convenient as you'd like.  (You could define crystalize outside the
loop, but I have it in the loop to keep it near the place where you
need it.)

. mylist = ["my","sample","list"]
. for item in mylist:
.     def crystalize(x):
.         return lambda self: func(self,x)
.     setattr(myclass,item,crystalize(item))

If you're hellbent on only using lambda, that can be done too:

.     setattr(myclass,item,(lambda x:(lambda self:
func(self,x)))(item))

You may not be aware of it, but what you're trying to do is called
"currying"; you might want to search the Python Cookbook for recipes on
it.


-- 
CARL BANKS




More information about the Python-list mailing list