Solving the "Late Binding" Problem in Python: A Simple Fix for Unexpected Behavior
Hafiz M. Zilehuda (Zile)
Sr. Software Engineer | Cloud (AWS, GCP) | Architect | Design softwares from scratch
Have you ever encountered the "late binding" problem in Python? It's a common issue that can lead to unexpected results when defining nested functions inside loops.
Consider this code:
functions = []
for number in range(8):
? ? def my_function():
? ? ? ? return number
? ? functions.append(my_function)
results = [function() for function in functions]
At first glance, you might expect the `results` list to contain the values [0, 1, 2, 3, 4, 5, 6, 7], since each function should return the value of `number` in the corresponding iteration of the loop. However, due to the late binding problem, all the functions actually return the value of `number` in the last iteration of the loop, which is 7. So the `results` list ends up containing 8 copies of the value 7.
[7, 7, 7, 7, 7, 7, 7, 7]
How To Fix It?
To fix this problem, you need to create a new scope for each function to capture the current value of `number` at the time the function is defined. One way to do this is to use a lambda function or a closure to create a new scope for each function.
领英推荐
Using a lambda function, you can pass `number` as a parameter to the function with a default value, like this:
functions = []
for number in range(8):
? ? my_function = lambda num=number: num
? ? functions.append(my_function)
results = [function() for function in functions]
Alternatively, you can use a closure to create a new scope for each function, like this:
functions = []
for number in range(8):
? ? def make_function(num):
? ? ? ? def my_function():
? ? ? ? ? ? return num
? ? ? ? return my_function
? ??
? ? functions.append(make_function(number))
results = [function() for function in functions]
By using one of these techniques to create a new scope for each function, you can avoid the late binding problem and get the expected results i.e [0, 1, 2, 3, 4, 5, 6, 7]
Have you encountered the "late binding" problem in your Python code? How did you solve it? Share your thoughts and experiences in the comments!