0

This:

l = ['A', 'B', 'C']
l = [lambda: i for i in l]
l = [i() for i in l]
print(l)

results in:

['C', 'C', 'C']

This is clearly due to the binding/scoping rules in Python, but I cannot figure it out. I would be grateful for an explanation?

Furthermore, how do I bind the lambda to the value of i in the loop, rather than the variable reference, so that the result is ['A', 'B', 'C']?

martineau
  • 119,623
  • 25
  • 170
  • 301
cmangla
  • 59
  • 1
  • 2
  • 1
    This really has *nothing* to do with `lambda`, it would work exactly the same if you used a regular function definition – juanpa.arrivillaga Oct 07 '21 at 20:33
  • 1
    Anyway, Python has *lexical* scope. Each lambda you create, `lambda : i` in the list comprehension, has a *free variable*, `i`. In fact, all the functions you create are closed over the exact same variable. When you *call* those functions (in the second list comprehension), they are *still bound to the same `i`*, which at this point, has the last value from the loop, i.e. `C`. – juanpa.arrivillaga Oct 07 '21 at 20:35
  • 1
    Anyway, the "correct" way of doing this is to use another local scope, something like `def func_maker(i): return lambda: i` now each individual lambda is closed over a unique variable that never changes. Equivalently, you can do `(lambda i: lambda : i)(i)`, but that is ugly...). Alternatively, a popular hack is to abuse a default argument, and you can do `lambda i=i: i` – juanpa.arrivillaga Oct 07 '21 at 20:42

0 Answers0