lambda closure question
Kent Johnson
kent37 at tds.net
Sat Feb 19 08:54:38 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))
>
> This attaches a list of functions to the class, making them bound
> methods when called from a class instance.
>
>
>>>>obj = myclass()
>>>>obj.list()
>
> list
> 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
The closure isn't bound until the scope containing it is exited. A simple workaround is to bind item
as a default argument to the lambda:
for item in mylist:
setattr(myclass, item, lambda self, item=item: func(self, item))
You can also make a helper function that returns the closure, the closure will be bound each time
the helper returns:
def make_f(item):
def f(self): func(self, item)
return f
mylist = ["my", "sample", "list"]
for item in mylist:
setattr(myclass, item, make_f(item))
Kent
More information about the Python-list
mailing list