Let's say that I want to create a list of functions funclist
, such that the fonctions of this list behave that way:
funclist[0](x) = 0
funclist[1](x) = x
funclist[2](x) = 2*x
funclist[3](x) = 3*x
Assuming that the list is too long (say of size 100) to define those functions one-by-one, a natural way to write this would be:
funclist = []
for k in range(100):
f = lambda x: k*x
funclist.append(f)
The problem is that this approach does not work, because of the way Python interprets local variables within function definitions. This is a problem I saw coming back often on this website, for instance here or here. Unfortunately, those users want to define constant functions, so the proposed solution (which is to define a local copy of the iterable variable k) do not work for me (it is also the same solution proposed in the Python FAQ). For instance, the following syntax does not work:
funclist = []
for k in range(100):
f = lambda local_k=k, x: local_k*x
funclist.append(f)
A solution I found is to do:
funclist = []
for k in range(10):
def f(x, product_factor=k): return x*product_factor
funclist.append(f)
which works as I want. I could also achieve the same result with the partial
function:
from functools import partial
def product(x,product_factor): return x*product_factor
funclist = []
for k in range(10):
funclist.append( partial(product, product_factor=k) )
So my question is : is there any way to achieve this result with lambda functions only? Or the fact that I have a "moving parameter" dooms me to define in a way or an other a function of two variables? Let me precise that I am asking this because I am trying to understand better how functions and currying work in Python.
Your lambda approach does not work because you have a keyword argument before a positional one. Just flip the order as you did in the working solutions:
funclist = [(lambda x, local_k=k: local_k*x) for k in range(100)]
>>> funclist[3](8)
24
>>> funclist[5](9)
45