为什么Python在字典中以某种方式用另一个函数覆盖我的函数?

huangapple go评论65阅读模式
英文:

Why is python somehow overwriting my function with another function in a dictionary?

问题

我有以下的代码,但运行失败:

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"  # 注意:这里出现了错误的 Python 行为
    assert F2S[2]() == "TWO"

在我的理解中,这段代码应该可以工作,我想知道为什么 Python 返回 TWO 作为 F2S[1]() 的结果。我尝试在字典中嵌套一些 lambda 函数。

英文:

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.

答案1

得分: 0

当你编写 lambda: value() 时,你会得到一个 lambda 函数,它将在调用时评估 value()。但是在完成 for key, value in F1S.items() 循环后,value 将具有 F1S 中最后一项的值,因此你创建的所有 lambda 函数都将使用这个最后的值,这种情况下返回 "TWO"

修复这个问题的一种方法是通过使用 lambda value=value: value() 来创建额外的绑定 value。这将为循环的每次迭代创建一个 value 变量,该变量将具有该迭代的正确值。

英文:

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.

huangapple
  • 本文由 发表于 2023年6月22日 17:59:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76530715.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定