I have a list of functions each of these takes a parameter.
I want to use a function of a library which takes functions but expects them to have no parameters.
So I want to create a list of new functions using lambda to pass the param "externally"
However the new list of functions doesn't yield the expected result.
(This is some minimal example)
def fun_a(param):
print("a")
def fun_b(param):
print("b")
def do_something(funs):
funs_out = []
for fun in funs:
funs_out.append(lambda: fun(0))
return funs_out
funs = [fun_a,fun_b]
funs[0](0) # prints a
funs[1](0) # prints b
funs_changed = do_something(funs)
#funs_changed = [lambda: f(0) for f in funs]
funs_changed[0]() # prints b ??? expected a
funs_changed[1]() # prints b
I tried funs_changed = [lambda: f(0) for f in funs]
before as it seems more pythonic, and then tried to use more explicit code (raw for loop) to find the root cause but without success.
What do I miss?
You can use functools.partial:
from functools import partial
def fun_a(param):
print("a")
def fun_b(param):
print("b")
def do_something(funs):
funs_out = []
for fun in funs:
funs_out.append(partial(fun, 0))
return funs_out
funs = [fun_a, fun_b]
funs[0](0) # prints a
funs[1](0) # prints b
funs_changed = do_something(funs)
# funs_changed = [partial(fun, 0) for f in funs]
funs_changed[0]() # prints a
funs_changed[1]() # prints b
From this answer:
Roughly, partial does something like this (apart from keyword args support etc):
def partial(func, *part_args): def wrapper(*extra_args): args = list(part_args) args.extend(extra_args) return func(*args) return wrapper