Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: Dictionary of Functions

30 views
Skip to first unread message

MRAB

unread,
Nov 15, 2012, 11:27:28 AM11/15/12
to pytho...@python.org
On 2012-11-15 16:04, Kevin Gullikson wrote:
> Hi all,
>
> I am trying to make a dictionary of functions, where each entry in the
> dictionary is the same function with a few of the parameters set to
> specific parameters. My actual use is pretty complicated, but I managed
> to boil down the issue I am having to the following example:
>
> In [1]: def test_fcn(a, x):
> ...: return a*x
> ...:
>
> In [2]: fcn_dict = {}
>
> In [3]: for i in [1,2,3]:
> ...: fcn_dict[i] = lambda x: test_fcn(i, x)
> ...:
>
> In [4]: fcn_dict
> Out[4]:
> {1: <function <lambda> at 0x102b42c08>,
> 2: <function <lambda> at 0x102b42b18>,
> 3: <function <lambda> at 0x102b42c80>}
>
> In [5]: fcn_dict[1](5)
> Out[5]: 15
>
> In [6]: fcn_dict[2](5)
> Out[6]: 15
>
> In [7]: fcn_dict[3](5)
> Out[7]: 15
>
>
> As you can see, all of the functions are returning the value that I want
> for fcn_dict[3]. If I make separate functions for each case instead of a
> dictionary it works, but I would really prefer to use dictionaries if
> possible. Is there a way to make this work?
>
It's looking up 'i' at the time that the function is called, which is
after the 'for' loop has finished and 'i' has been left as 3.

What you need to do is capture the current value of 'i'. The usual way
is with a default argument:

for i in [1,2,3]:
fcn_dict[i] = lambda x, i=i: test_fcn(i, x)

Chris Kaynor

unread,
Nov 15, 2012, 12:13:20 PM11/15/12
to pytho...@python.org
On Thu, Nov 15, 2012 at 8:04 AM, Kevin Gullikson
<kevin.g...@gmail.com> wrote:
> Hi all,
>
> I am trying to make a dictionary of functions, where each entry in the
> dictionary is the same function with a few of the parameters set to specific
> parameters. My actual use is pretty complicated, but I managed to boil down
> the issue I am having to the following example:
>
> In [1]: def test_fcn(a, x):
> ...: return a*x
> ...:
>
> In [2]: fcn_dict = {}
>
> In [3]: for i in [1,2,3]:
> ...: fcn_dict[i] = lambda x: test_fcn(i, x)
> ...:

In this case, I would recommend using functools.partial instead of a lambda.
It will solve this problem (although MRAB's solution will as well), is
trivially faster (likely insignificant in any real application), and,
IMO, clearer:

for i in [1,2,3]:
fcn_dict[i] = functools.partial(test_fcn, i)

Note that this only works if you are either only specifying the first
arguments by position, or specifying arguments by keyword. There is no
way to specify the second argument by position; you'd have to pass it
as a keyword argument.
0 new messages