0

I was struggling with weird bug in my code. Following code is simple replication of that bug:

import random

array = []
for _ in range(0,5):
    rand = random.randint(0,7)
    print(f"adding lambda for rand = {rand}")
    array.append(lambda : print(rand))

for e in array:
    e()

My prediction was that e() would print exactly the same numbers as the first loop but it didn't. After some time I figured it out that rand is always the same place in memory and only the last change to its value will be used in lambda execution. The thing is as much as I understand how it works I don't understand why would someone possibly make programming language work this way. So here's my question: Why local variables in python point to the same place in memory even though it's not declared before the loop(scope)?

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
  • 1
    Because the function you create is closed over `rand`. And the value of `rand` is always the *last value from your loop*. – juanpa.arrivillaga Sep 25 '20 at 23:12
  • Although note, `rand` is global in this case. – juanpa.arrivillaga Sep 25 '20 at 23:18
  • @juanpa.arrivillaga what would make value passed to lambda work as I expected at first? – Arek Żyłkowski Sep 25 '20 at 23:22
  • 1
    Well, the "correct" way to do this is to *force* the creation of a local variable that doesn't change. Create a factory function, `def func_maker(rand): return lambda: rand` then use `array.append(func_maker(rand))`. There is also a common idiom in python to use (or abuse) default paramters, and you could just do `array.append(lambda rand=rand: rand)` – juanpa.arrivillaga Sep 25 '20 at 23:24
  • 1
    Because note, **you aren't passing in a value anywhere**. You are simply referencing a free variable, and that variable resolves to `rand`. So of course, it gives you the same value as what `print(rand)` would give you there. Also note, this question has noting to do with memory management. – juanpa.arrivillaga Sep 25 '20 at 23:25
  • 1
    Okay, thank you very much for clearing it out. – Arek Żyłkowski Sep 25 '20 at 23:34

0 Answers0