Weird lambda behavior
clp2 at rebertia.com
Wed Apr 22 13:59:14 CEST 2009
On Wed, Apr 22, 2009 at 4:50 AM, Rüdiger Ranft <_rdi_ at web.de> wrote:
> Hi all,
> I want to generate some methods in a class using setattr and lambda.
> Within each generated function a name parameter to the function is
> replaced by a string constant, to keep trail which function was called.
> The problem I have is, that the substituted name parameter is not
> replaced by the correct name of the function, but by the last name the
> for loop has seen.
> import unittest
> class WidgetDummy:
> '''This class records all calls to methods to an outer list'''
> def __init__( self, name, calls ):
> '''name is the name of the object, which gets included into a
> call record. calls is the list where the calls are appended.'''
> self.name = name
> self.calls = calls
> for fn in ( 'Clear', 'Append', 'foobar' ):
> func = lambda *y,**z: self.__callFn__( fn, y, z )
> setattr( self, fn, func )
Common wart to run into as of late. fn (in the lambda) doesn't get
evaluated until the call-time of the lambda, by which point the loop
has finished and the loop variable has been changed to its final
value, which is used by the lambda.
#exact syntax may vary with your version of Python, but you should be
able to get the idea
func = lambda *y,**z, fn=fn: self.__callFn__( fn, y, z )
The default argument value gets evaluated at definition-time, thus
forcing the right value of fn within the function.
I have a blog:
More information about the Python-list