Weird lambda behavior
_rdi_ at web.de
Wed Apr 22 14:52:47 CEST 2009
Chris Rebert schrieb:
> 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 =ame
>> self.calls =alls
>> for fn in ( 'Clear', 'Append', 'foobar' ):
>> func =ambda *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.
Doh! I wasn't aware of the point when the lambda expression is evaluated.
> #exact syntax may vary with your version of Python, but you should be
> able to get the idea
> func =ambda *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.
Thank you, I replaced the direct assignment with a proxy function call,
and now it works.
def __init__( self, name, calls ):
self.name = name
self.calls = calls
setattr( self, fn, lambda *y,**z: self.__callFn__(x, y, z) )
for fn in ( 'Clear', 'Append', 'foobar' ):
GPG encrypted mails preferred.
GPG verschlüsselte Mails bevorzugt.
---> http://chaosradio.ccc.de/media/ds/ds085.pdf Seite 20 <----
More information about the Python-list