0

Say I want to create a list of 5 functions, where the i-th function just adds i to the argument. The naive code

L = []
for i in range(5):
    def f(z):
        return z+i
    L.append(f)

apparently does not work: print([f(0) for f in L]) yields [4, 4, 4, 4, 4]. Similarly,

L = [lambda z: z+i for i in range(5)]

does not work either. The value of i at the time when the function is defined is not fixed to f. A clumsy hack is

tmp = ["lambda z:z+{}".format(i) for i in range(5)]
L = eval("[" + ",".join(tmp) + "]")

But I'm sure that there is a clean solution! Which is it?

  • 1
    To create closures that use a variable (like `i`) you need to bind it during definition time: https://stackoverflow.com/questions/10452770/python-lambdas-binding-to-local-values – rdas Feb 06 '20 at 17:11

2 Answers2

1
def get_func(i):
    return lambda z: z + i

L = [get_func(i) for i in range(5)]
Peter Collingridge
  • 10,849
  • 3
  • 44
  • 61
0

According to an answer to a related question (thanks to rdas for the link in the comments), default arguments are evaluated when a function is created, not when it is called. So this alternative to Peter Collingridge's suggestion works too:

L = []
for i in range(5):
    def f(z, i=i):
        return z+i
    L.append(f)

or

L = [lambda z, i=i: z+i for i in range(5)]