3

Id like to define a list of functions by a list of parameters, to actually compose a potential from a finite number of monopoles and dipoles.

Functions in python list, however, for some reason do not behave as expected (by me).

The following example:

def function(coefficients):
  phi = []
  i = 0
  for y in coefficients:
    f = lambda x: y*(x**i)
    i += 1
    phi.append(f)
    print f(2)
  return phi

> phi = function([1,2,3])
2
8
24

> k0 = phi[0]
> k1 = phi[1]
> k2 = phi[2]

> print k0(2), k1(2), k2(2)
24 24 24

Always the last function in the list is retrieved independent of which function is picked from the list.

Any ideas?

Thanks in advance.

  • 2
    f will use the last known value of y, not the value that y had when you created the lambda. See also [Local variables in Python nested functions](http://stackoverflow.com/questions/12423614/local-variables-in-python-nested-functions) – Kevin Apr 09 '14 at 15:55

1 Answers1

5

The lambda function holds a reference to the variable y, because of the closure property. So, all the functions have the reference to the same object and they will get the last value of y during the invocation. To fix this,

f = lambda x,y=y,i=i: y*(x**i)

Now, we have created another parameter y and that has the default value y. It makes the function depend on a local reference now. So, even if the value of y changes in the loop, the lambda function no longer refers to that y.

Note: The same explanation is applicable to the variable i as well.

To make things very clear, I would recommend using different variable names

f = lambda x, z=y, j=i: z * (x ** j)

Note: Your original output was 2 8 24. That was because, when you invoke the function, i got incremented and I don't think that is what you really wanted. The actual output should have been 1 4 12.

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • Thanks. Nice solution using default values. Originally tried to use deepcopy to resolve the redefinition of the parameters in the lambda function, but did not realize that deepcopy is also executed at execution time of the lambda function, and thus the parameter has already been redefined. Thus, was quite puzzeld what is going on. Thanks again. – YetAnotherCoda Apr 09 '14 at 16:49