1

I have a code listed below. I am not sure why the returns should be 4

def create_multiplier():
    return [lambda x: x*i for i in range(10)]
f = create_multiplier()
print f[1](1) 

The result turns out to be 4. I'm familiar with the lambda function something like lambda x: x*2 but very confused about this one. It seems like it get the last iterate of i for example:

   for i in range(5):
       i
   print i 
April
  • 23
  • 6
  • 1
    In my Python 3.5.2, when I use outer parentheses in the print statement (to avoid a syntax error), I get the result `9` as the printout. – Rory Daulton Nov 09 '16 at 00:28
  • Are you sure you got a 4 instead of a 9? If so, are you sure the code you posted exactly matches the code you ran, including things like the argument to `range`? – user2357112 Nov 09 '16 at 00:30
  • `print(f[0])` gives you `.. at 0x7fa64f1aea60>`. But what is that thing? Since your `lambda` references local variable `i`, it is a closure bound to the locals of the `create_multiplier` function. (python creates an object each time a function is executed and that object holds its locals). When the function exits, its `i` variable is 9 so 9 is what you get in the closures. Since all 10 of those lambdas end up doing exactly the same thing, I suspect its a bug in the code. – tdelaney Nov 09 '16 at 00:33

1 Answers1

4

In Python, the value of a closure variable is frozen when the outer function ends, not when the inner function is created. So yes, it is using the last value of i. To avoid this, you can use a default argument:

return [lambda x, i=i: x*i for i in range(10)]

Edit: As a comment notes, the closure variable isn't technically frozen, it's just that in your situation there isn't any way to change it. But there are other situations where it could be changed.

kindall
  • 178,883
  • 35
  • 278
  • 309
  • "the value of a closure variable is frozen when the outer function ends" - not even then, because an inner function using `nonlocal` could still change it. The value never gets frozen; it's looked up every time the variable gets used. – user2357112 Nov 09 '16 at 00:28
  • 1
    @user2357112 You are technically correct... the best kind of correct. – kindall Nov 09 '16 at 00:40