The problem, which is a classic
"gotcha", is
that the i referenced in the lambda functions is not looked up until the
lambda function is called. At that time, the value of i is the last value it
was bound to when the for-loop ended, i.e. 2.
If you bind i to a default value in the definition of the lambda functions, then each i becomes a local variable, and its default value is evaluated and bound to the function at the time the lambda is defined rather than called.
Thus, when the lambda is called, i is now looked up in the local scope, and its default value is used:
In [177]: bases = [lambda x, i=i: x**i for i in range(3)]
In [178]: print([b(5) for b in bases])
[1, 5, 25]
For reference:
- Python scopes and namespaces