Nested functions and lambdas can reference variables defined in enclosing scopes. This can create tricky bugs when the variable and the function are defined in a loop. If the function is called in another iteration or after the loop finishes, it will see the variables' last value instead of seeing the values corresponding to the iteration where the function was defined.
* it increases the risk of introducing a bug when the code is refactored or when dependencies are updated. See an example with the builtin "map" below.
One solution is to add a parameter to the function/lambda and use the previously captured variable as its default value. Default values are only executed once, when the function is defined, which means that the parameter's value will remain the same even when the variable is reassigned in following iterations.
mylist.append(lambda i=i: i) # passing the variable as a parameter with a default value
def func(i=i): # same for nested functions
return i
mylist.append(func)
def example_of_api_change():
""""
This will work for both python 2 and python 3.
"""
lst = []
for i in range(5):
lst.append(map(lambda x, value=i: x + value, range(3))) # Passing "i" as a default value
for sublist in lst:
print(list(sublist))
----
== Exceptions
No issue will be raised if the function or lambda is directly called in the same loop. This still makes the design difficult to understand but it is less error prone.