Problem:
I want to create a list of lambda functions using **kwargs
which are iterated in the list.
Similar questions (e.g., e.g.) exist, but they do not consider iterating over **kwargs
.
The problem, as before, is that the value of kwargs
in the lambda function is evaluated "lazily" after creation in the list, meaning the last value assigned during the iteration is passed to all lambda functions.
I've verified this is a 'problem' for classic loops as well as comprehensions.
(2a)
is not, having the value argset
from the last iteration of the comprehension assigned to all **kwargs
.
(3a)
is worse, having both the values of argset
and i
from the last iteration assigned to x
and **kwargs
.
MWE
Code
def strfun(x,**kwargs):
return 'x: {} | kwargs: {}'.format(x,kwargs)
argsets = [
{'foo': 'bar'},
{'baz': 'qux'},
]
# (1) expected behaviour:
print '(1) '+str([strfun(i,**argset) for i,argset in enumerate(argsets)])
# (2) unexpected behaviour:
funs = [lambda x: strfun(x,**argset) for argset in argsets]
print '(2) '+str([fun(i) for i,fun in enumerate(funs)])
# (3) unexpected behaviour:
funs = [lambda : strfun(i,**argset) for i,argset in enumerate(argsets)]
print '(3) '+str([fun() for fun in funs])
Output:
(1) ["x: 0 | kwargs: {'foo': 'bar'}", "x: 1 | kwargs: {'baz': 'qux'}"]
(2) ["x: 0 | kwargs: {'baz': 'qux'}", "x: 1 | kwargs: {'baz': 'qux'}"]
(3) ["x: 1 | kwargs: {'baz': 'qux'}", "x: 1 | kwargs: {'baz': 'qux'}"]
(1)
is "correct".
(2)
is not, having the last value of argsets
assigned to **kwargs
for all functions ({'baz': 'qux'}
).
(3)
is worse, having the last value of both i
and argsets
assigned to x
and **kwargs
for all functions (1
and {'baz': 'qux'}
).