0

I had written code where I passed a generator of lambda functions to a varargs function that iterates over the generator and applies the function to a container. But the result was not as expected. Only the last function was called. But n times, where n is the number of functions in the generator. Consider the following MWE:

>>> def f(*fs):
...     for f in fs:
...         print(f.__code__)
...         print(f(1))
... 
>>> f(*(lambda x : k*x for k in range(3)))
<code object <lambda> at 0x7fe1ca683130, file "<stdin>", line 1>
2
<code object <lambda> at 0x7fe1ca683130, file "<stdin>", line 1>
2
<code object <lambda> at 0x7fe1ca683130, file "<stdin>", line 1>
2

I next tested going over a list of lambdas without the function call and varargs part. Same result.

>>> for f in [lambda x : k*x for k in range(3)]:
...     print(f.__code__)
...     print(f(1))
... 
<code object <lambda> at 0x7fe1ca634b30, file "<stdin>", line 1>
2
<code object <lambda> at 0x7fe1ca634b30, file "<stdin>", line 1>
2
<code object <lambda> at 0x7fe1ca634b30, file "<stdin>", line 1>
2

Then I tested it with just a generator. The printing of f.__code__ shows, that the function is redefined on the spot. It is always the same address but with different content. So the previous function gets overwritten each time the generator proceeds.

>>> for f in (lambda x : k*x for k in range(3)):
...     print(f.__code__)
...     print(f(1))
... 
<code object <lambda> at 0x7fe1ca683130, file "<stdin>", line 1>
0
<code object <lambda> at 0x7fe1ca683130, file "<stdin>", line 1>
1
<code object <lambda> at 0x7fe1ca683130, file "<stdin>", line 1>
2

Why is that and how can I pass a generator of lambdas to a function without ending up with n times the last function?

lo tolmencre
  • 3,804
  • 3
  • 30
  • 60
  • 1
    Possible duplicate of [Python lambda's binding to local values](https://stackoverflow.com/questions/10452770/python-lambdas-binding-to-local-values) .. maybe not exactly a dupe but related – pault Jul 19 '19 at 20:35
  • Also, check this out: https://stackoverflow.com/q/40685006/198633 – inspectorG4dget Jul 19 '19 at 20:41
  • 1
    Why do you claim default values don't solve this? `f(*(lambda x, k=k: k*x for k in range(3)))` does exactly what I'd expect. See https://sopython.com/canon/30/why-do-my-lambda-functions-or-nested-functions-created-in-a-loop-all-use-the-las/ – jonrsharpe Jul 19 '19 at 20:49
  • @jonrsharpe Ah right, I did something wrong then. – lo tolmencre Jul 19 '19 at 20:50
  • The reason it works with the generator is that `k` only changes at the time that the next `f` is computed from the generator, and then it's used immediately. – Karl Knechtel Aug 19 '22 at 12:45

0 Answers0