So here is some code that simplifies what I’ve been working on:
vars = {
'a':'alice',
'b':'bob',
}
cnames = ['charlie', 'cindy']
commands = []
for c in cnames:
kwargs = dict(vars)
kwargs['c'] = c
print kwargs
commands.append(lambda:a_function(**kwargs))
print commands
def a_function(a=None, b=None, c=None):
print a
print b
print c
for c in commands:
print "run for "+ repr(c)
c()
And here is its output:
{'a': 'alice', 'c': 'charlie', 'b': 'bob'}
{'a': 'alice', 'c': 'cindy', 'b': 'bob'}
[<function <lambda> at 0x1001e9a28>, <function <lambda> at 0x1001e9e60>]
run for <function <lambda> at 0x1001e9a28>
alice
bob
cindy
run for <function <lambda> at 0x1001e9e60>
alice
bob
cindy
I would expect to get charlie, then cindy, why is cindy being displayed twice?
A function’s body isn’t ran until the function is called. When you do
lambda: a_function(**kwargs),kwargsisn’t looked up until you actually call the function. At that point it’s assigned to the last one you made in the loop.One solution that gets the result you want would be to do
commands.append(lambda kwargs=kwargs: a_function(**kwargs))