Scope Variable With A Loop
Solution 1:
To clarify a bit more on the subject, the reference to i
does not change within the lambda - you see that each iteration of i
generates a new object:
def makeActions():
acts=[]
for i in range(5):
print('i:', i, 'object id:', id(i))
acts.append(lambda: id(i))
print('final i:', i, 'object id:', id(i))
return acts
acts=makeActions()
print([fn() for fn in acts])
Returns
i: 0objectid: 140418781832928
i: 1objectid: 140418781832960
i: 2objectid: 140418781832992
i: 3objectid: 140418781833024
i: 4objectid: 140418781833056
final i: 4objectid: 140418781833056
[140418781833056, 140418781833056, 140418781833056, 140418781833056, 140418781833056]
The reference from i
always points to its last assigned object, thus the id of i
will not change after its last alteration.
If you want to keep the value at the time of the lambda creation, you need to "trap" the value of the reference at the desired place and time, for instance you could delegate the lambda creation to a function:
defdelegated(d):
returnlambda: id(d)
defmakeDelegatedActions():
acts=[]
for i inrange(5):
print('i:', i, 'object id:', id(i))
acts.append(delegated(i))
print('final i:', i, 'object id:', id(i))
return acts
acts=makeDelegatedActions()
print([fn() for fn in acts])
Which returns
i: 0objectid: 140418781832928
i: 1objectid: 140418781832960
i: 2objectid: 140418781832992
i: 3objectid: 140418781833024
i: 4objectid: 140418781833056
final i: 4objectid: 140418781833056
[140418781832928, 140418781832960, 140418781832992, 140418781833024, 140418781833056]
Solution 2:
Each lambda will just know to fetch i
from its enclosing scope, which is the makeActions
call. They don't actually do so until they're called themselves. i
is the same name within the same scope, it just happens to take different values during the loop, and will simply hold the last value after the loop finishes. So the lambdas just ended up creating 5 identical functions.
A variation that can work:
defexpgen(n):
defmyexp(x):
return n**x
return myexp
acts = [expgen(i) for i inrange(5)]
In this case, the scope that n
is fetched from is that of expgen
, which had distinct calls in the list comprehension, and each function will work independently.
Post a Comment for "Scope Variable With A Loop"