0

I'm creating an array of lambda function that way (shift by n bits over a 16 bits representation but the problem is independent of the function role):

>>> lshifting=[lambda x:(x<<y) & 65535 for y in range(0,16)]

I'm expecting each lambda to use the value y had when the function was instanciated.

If I check, each lambda is a different object in memory:

>>> print (lshifting)
[<function <lambda> at 0x7f11b632fde8>, <function <lambda> at 0x7f11b632fe60>, <function <lambda> at 0x7f11b632fed8>,....

However, the behaviour is not what I expect:

>>> [x(1) for x in lshifting]
[32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768]

>>> [(1<<y) & 65535 for y in range(0,16)]
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768]

I'm obviously expecting both result to be identical while all lambdas seems to have been created with a reference to the temporary y variable and then, when used, take the last known value of this variable.

I got 2 questions:

  • is this an expected behaviour ?
  • what is the pythonic way to instanciate functions dynamically? (typical example is Currying)
Bruce
  • 7,094
  • 1
  • 25
  • 42
  • 1
    Also see http://stackoverflow.com/questions/10452770/python-lambdas-binding-to-local-values and http://stackoverflow.com/questions/233673/lexical-closures-in-python – PM 2Ring Jan 05 '16 at 11:40
  • 2
    One common way to deal with this is shown in the accepted answer in my 1st link: provide `y` as a default keyword arg, eg `lambda x,y=y:(x< – PM 2Ring Jan 05 '16 at 11:44
  • I ended up writing a wrapper class and using it as a functor, easier to read. Nasty one though :-/ – Bruce Jan 05 '16 at 13:30

0 Answers0