lambda closure question

Ted Lilley ted.lilley at gmail.com
Sat Feb 19 02:42:31 EST 2005


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))

This attaches a list of functions to the class, making them bound
methods when called from a class instance.  The functions are all
similar except that they know their name through the item argument.
The lambda takes the underlying function and preloads it with its name,
and since lambdas support closures, it remembers the item variable that
was used to create it when it is actually called like so:

>>>obj = myclass()
>>>obj.list()
list

That's great, since I can write a generic function that just needs to
know its name to make a slight modification to its behavior, then
attach it a bunch of times to a class under different names.

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.
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.

Am I missing something?  Help.




More information about the Python-list mailing list