When a lambda is created, it doesn’t make a copy of the variables in the enclosing scope that it uses. It maintains a reference to the environment so that it can look up the value of the variable later. There is just one m
. It gets assigned to every time through the loop. After the loop, the variable m
has value 'mi'
. So when you actually run the function you created later, it will look up the value of m
in the environment that created it, which will by then have value 'mi'
.
One common and idiomatic solution to this problem is to capture the value of m
at the time that the lambda is created by using it as the default argument of an optional parameter. You usually use a parameter of the same name so you don’t have to change the body of the code:
for m in ('do', 're', 'mi'):
funcList.append(lambda m=m: callback(m))