0

I have the following code, which fails:

def test_function_combining_wrong():
    def one():
        print("ONE")
        return "ONE"
    
    def two():
        print("TWO")
        return "TWO"
    
    F1S = {
        1: one,
        2: two,
    }
    F2S = {
        **{key: lambda: value() for key, value in F1S.items()},
    }
    print("1st Call")
    assert F1S[1]() == "ONE"
    assert F1S[2]() == "TWO"
    print("2nd Call")
    assert F2S[1]() == "ONE"  # ATTENTION: THIS IS WRONG WEIRD PYTHON STUFF
    assert F2S[2]() == "TWO"

In my head this code should work and I would like to know why Python returns TWO for the F2S[1](). I'm trying to nest some lambda functions together in dictionaries.

danielmoessner
  • 339
  • 3
  • 18

1 Answers1

0

When you write lambda: value(), you get a lambda function that will evaluate value() when it's called. But after the for key, value in F1S.items() loop is finished, value will have the value of the last item in F1S so all the lambda functions you created will use this last value which in this case returns "TWO".

One way to fix this is to make an extra binding for value, by using lambda value=value: value() instead. This will create a value variable for each iteration of the loop which will have the correct value for that iteration.

interjay
  • 107,303
  • 21
  • 270
  • 254
  • This answer is correct, but in this case, the easier thing to do would be to replace the whole lambda with just `value`. – Jasmijn Jun 22 '23 at 11:16
  • 3
    @Jasmijn That's true. I assumed this was a simplified version of the code and the original might do more than just `value()`, so I suggested the more general approach. – interjay Jun 22 '23 at 11:22