You are accessing the same object each time, since dict
are not ordered, and accessing them by index does not do what you expect
funcs = {
idx: lambda: print(idx, end=' ') for idx in range(5)
}
for f in funcs:
print(f, id(f))
print('#'*20)
for idx in range(5):
print(id(funcs[idx]()))
0 1477866096
1 1477866128
2 1477866160
3 1477866192
4 1477866224
####################
4 1477430720
4 1477430720
4 1477430720
4 1477430720
4 1477430720
The previous explanation is wrong. What actually happens is this:
The lambdas were constructed using idx in range(5)
. When a lambda is called, no matter the caller idx parameter (i.e. it doesn't matter what idx
is insidefuncs[idx]()
) the lambda is using the idx
from range(5)
. Since the range(5)
now (at its end) points to 4, that is the idx
each lambda uses, resulting in all of them printing 4.
The lambda are different objects, but they still all use the current inner idx
.
Here is an example that helped me:
ls=[]
for i in range(2):
ls.append(lambda : print(i))
for f in ls:
print(id(f), end=' ')
f()
for i in range(3,5):
ls.append(lambda : print(i))
for f in ls:
print(id(f), end=' ')
f()
44467888608 1 # 1st lambda - uses the last idx (for range was 2)
44467888336 1 # 2nd lambda - uses the last idx (for range was 2)
44467888608 4 # 1st lambda - uses the current last idx (2nd for range was 5)
44467888336 4 # 2nd lambda - uses the current last idx (2nd for range was 5)
44467921240 4 # 3rd + 4th lambdas
44467921512 4