0

I'd appreciate it if anyone could help me with this issue (in Python). I have the function

f(x) = r*x*(1-x)

and I'd like to define it repeatedly for about 26 different values of r, ranging from 3.8 to 3.85 (I'd like to ultimately plot the cobweb plots for these functions and compare them, and I don't want to have r as a parameter to my function). So I'd like to store these 26 functions within a list and then access them later. I have the following code, but instead of storing different function definitions, it only stores the function with the first value of r=3.8 in all 26 spots in the list.

r_list = []
r = 3.8
r_list.append(r)
for n in range(25):
    new_r = round(r + 0.002, 3)
    r_list.append(new_r)
    r = new_r

f_t = []
for r in r_list:
   f_t.append(lambda x: r*x*(1-x))

print r_list
print f_t
print f_t[0](3)
print f_t[2](3)

So my output for these print statements is:

[3.8, 3.802, 3.804, 3.806, 3.808, 3.81, 3.812, 3.814, 3.816, 3.818, 3.82, 3.822, 3.824, 3.826, 3.828, 3.83, 3.832, 3.834, 3.836, 3.838, 3.84, 3.842, 3.844, 3.846, 3.848, 3.85]

[<function <lambda> at 0x0000000008739908>, <function <lambda> at 0x0000000008739978>, <function <lambda> at 0x00000000087399E8>, <function <lambda> at 0x0000000008739A58>, <function <lambda> at 0x0000000008739AC8>, <function <lambda> at 0x0000000008739B38>, <function <lambda> at 0x0000000008739BA8>, <function <lambda> at 0x0000000008739C18>, <function <lambda> at 0x0000000008739C88>, <function <lambda> at 0x0000000008739CF8>, <function <lambda> at 0x0000000008739D68>, <function <lambda> at 0x0000000008739DD8>, <function <lambda> at 0x0000000008739E48>, <function <lambda> at 0x0000000008739EB8>, <function <lambda> at 0x0000000008739F28>, <function <lambda> at 0x0000000008739F98>, <function <lambda> at 0x0000000008739828>, <function <lambda> at 0x000000000873D048>, <function <lambda> at 0x000000000873D0B8>, <function <lambda> at 0x000000000873D198>, <function <lambda> at 0x000000000873D208>, <function <lambda> at 0x000000000873D278>, <function <lambda> at 0x000000000873D2E8>, <function <lambda> at 0x000000000873D358>, <function <lambda> at 0x000000000873D128>, <function <lambda> at 0x00000000165452E8>]

-23.1
-23.1

And I tried all of the suggestions from How can I define functions in a for loop?, but I still can't get it to work. Any ideas? I'd really appreciate it.

Community
  • 1
  • 1
Lindsey
  • 13
  • 1
  • you have two `r`s, best changing your for loop variable name just to avoid an ambiguitity – OMGtechy Nov 20 '14 at 19:20
  • Looks like we've got a compulsive downvoter on this page. – Marcin Nov 20 '14 at 19:24
  • Thanks to all the answers, I see I just needed to localize the r. I appreciate your help! But does anyone have any idea why the following happens: I have my function cobweb(f, x0, n, xmin, xmax, ymin, ymax) that plots the cobweb graphs of a function, but when I call this function using f_t[0] for example, it produces an endless loop? Endless plots are produced on my screen, causing it to crash. This only happens using the f_t functions. Any ideas? – Lindsey Nov 20 '14 at 19:34

3 Answers3

3
for r in r_list:
   f_t.append(lambda x: r*x*(1-x))

Lambdas don't capture the value, they capture the variables. Here the r is the same in all lambdas, and its value is the last value it took in the loop.

You can fix it by manually capturing the value:

   f_t.append(lambda x,r=r: r*x*(1-x))

Small example demonstrating the behaviour:

l=[1, 2, 3]
l2=[]
for r in l:
   l2.append(lambda: r)
l2[0]()   # 3

l2=[]
for r in l:
   l2.append(lambda r=r: r)
l2[0]()   # 1
Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
1

The r inside the lambda function is the r of the outer context, so it has the value at the time, the function is called. To avoid this, localize r:

f_t.append(lambda x, r=r: r*x*(1-x))
Daniel
  • 42,087
  • 4
  • 55
  • 81
0

I don't want to have r as a parameter to my function

Why not?

it only stores the function with the first value of r=3.8 in all 26 spots in the list.

That doesn't sound right. What it should be doing is capturing the variable r, and it should have the value that r has from time to time.

What you want to do is define your lambda like so:

for r in r_list:
   f_t.append(lambda x, r=r: r*x*(1-x))

This way, the r local to the lambda is assigned the value the external r has at the time of definition.

Marcin
  • 48,559
  • 18
  • 128
  • 201