I've stumbled upon something that hurts my brain. Consider the following
fs = []
for i in range(3):
fs.append(lambda : normal(i, .001))
print mean([fs[-1]() for j in range(1000)])
print [mean([fs[i]() for j in range(1000)]) for i in range(3)]
which returns, e.g.,
-1.38651717873e-05 |
1.00003545604 |
1.99999343229 |
[2.0530899455777235e-05, 0.99995283932453838, 2.0000045292311737]
as expected. Now modify things slightly
fs = []
for i in range(3):
mu = i
fs.append(lambda : normal(mu, .001))
print mean([fs[-1]() for j in range(1000)])
print [mean([fs[i]() for j in range(1000)]) for i in range(3)]
and we get
5.56620751611e-06 |
0.999999076252 |
1.99995161119 |
[2.0000016397219098, 1.9999853403014964, 2.0000209870831158]
i.e. 2 for each of the ones outside the loop. After kerploding my brain, I remembered that references/scoping in python are evil, and it appears the answer is that the mu passed to normal is being stored by reference rather than by value (even though mu should be scoping out in a normal language). Is that what is happening? How can I avoid similar madness in future coding?