Basically the problem is that the variable k, in this case, continually changes as the loop iterates. This means that all things which are pointing to the variable "k" are pointing to the same value at all times.
There are a couple of ways to solve this. This is perhaps the most common.
def f(x, k=k):
# This sets k as a locally bound variable which is evaluated
# at the time the function is created.
return x + 2*k
The detriment is that this solution will allow a later function to call the newly created functions with a different value of k. This means you could call f("cat","dog") and get "catdogdog" as a return. While this is not the end of the world, it certainly isn't intended.
However, you could also do something like this:
def f_maker(k):
# Create a new function whose variable "k" does not exist in outside scope.
def f(x):
return x + 2*k
return f
fs = []
for k in range(0, 10):
fs.append(f_maker(k))
fs[0](1)