0

I'm looking to create and store a specific function for each key of a dictionary. However, I've noticed that whenever I try to iterate through my set of keys (By creating an iterable then manually iterating, using a comprehension, and by the "for" loop), all of the functions turn out the same:

>>> numbers = list(range(10))
>>> functions = {}
>>> for number in numbers:
        functions[number] = lambda: number
# I'd expected the call functions[2]() should return 2

>>> two_function = functions[2]
>>> two()
9

Could someone explain why this happens and how to fix this?

M.Stevens
  • 41
  • 2
  • See ["Why do lambdas defined in a loop with different values all return the same result?"](https://docs.python.org/3/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result). – Warren Weckesser Jul 27 '21 at 19:22
  • Consider the result of `print(number)` – juanpa.arrivillaga Jul 27 '21 at 19:35
  • Note, the "principled" way to do this is to use a factory function: `def make_func(number): return lambda: number` and then use `functions[number] = make_func(number)` in your loop.or you can take advantage of the default argument trick, although that may be considered a bit hackey, but it is a common enough idiom – juanpa.arrivillaga Jul 27 '21 at 19:42

1 Answers1

1

This is a fun little twist in Python. The lambda there is returning the number object. By the time the loop ends, the number object has the value 9. What you need is a trick called "capturing":

    functions[number] = lambda n=number: n

That "captures" the value at the point the lambda is defined.

Tim Roberts
  • 48,973
  • 4
  • 21
  • 30
  • I wouldn't say this is really a twist in Python, it is merely the consequence of lexical scoping, which is pretty standard among modern languages. It is no more exotic than `x = 0; def foo(): print(x); x= 1; foo()` – juanpa.arrivillaga Jul 27 '21 at 19:39