python - What do (lambda) function closures capture? -


recently started playing around python , came around peculiar in way closures work. consider following code:

adders=[0,1,2,3]  in [0,1,2,3]:    adders[i]=lambda a: i+a  print adders[1](3) 

it builds simple array of functions take single input , return input added number. functions constructed in for loop iterator i runs 0 3. each of these numbers lambda function created captures i , adds function's input. last line calls second lambda function 3 parameter. surprise output 6.

i expected 4. reasoning was: in python object , every variable essential pointer it. when creating lambda closures i, expected store pointer integer object pointed i. means when i assigned new integer object shouldn't effect created closures. sadly, inspecting adders array within debugger shows does. lambda functions refer last value of i, 3, results in adders[1](3) returning 6.

which make me wonder following:

  • what closures capture exactly?
  • what elegant way convince lambda functions capture current value of i in way not affected when i changes value?

your second question has been answered, first:

what closure capture exactly?

scoping in python dynamic and lexical. closure remember name , scope of variable, not object it's pointing to. since functions in example created in same scope , use same variable name, refer same variable.

edit: regarding other question of how overcome this, there 2 ways come mind:

  1. the concise, not strictly equivalent way one recommended adrien plisson. create lambda argument, , set argument's default value object want preserved.

  2. a little more verbose less hacky create new scope each time create lambda:

    >>> adders = [0,1,2,3] >>> in [0,1,2,3]: ...     adders[i] = (lambda b: lambda a: b + a)(i) ...      >>> adders[1](3) 4 >>> adders[2](3) 5 

    the scope here created using new function (a lambda, brevity), binds argument, , passing value want bind argument. in real code, though, have ordinary function instead of lambda create new scope:

    def createadder(x):     return lambda y: y + x adders = [createadder(i) in range(4)] 

Comments

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

ios - Change Storyboard View using Seague -