python中奇怪的行为与la​​mbda函数的dict

时间:2016-01-01 08:43:18

标签: python python-3.x lambda

我编写了一个函数来生成一个lambda常量函数的字典(它是一个更复杂的函数的一部分,但我把它简化为下面的代码):

def function(a):
    _interpolators = {}
    for key in a.keys():
        _interpolators[key] = lambda t: a[key]

    def _interpolate(t):
        return {key:f(t) for (key,f) in _interpolators.items()}
    return _interpolate

if __name__ == '__main__':    
    d = {"foo": 2, "bar":4}
    f = function(d)
    print(f(0)["bar"])

在OSX El Capitan上使用Python 3.5.1,程序的输出是随机的。它可以是24,而我希望只有4。我不太明白这种行为。

请注意,python 2.7.10似乎没有出现“bug”,而且当我多次运行程序时,我总是得到4

它是python 3.5.1中的某种错误还是我错过了一些明显的东西?

2 个答案:

答案 0 :(得分:1)

lambda中的

programChange()取自函数key的范围。所以它具有function中最后一个元素的值。字典中键的顺序是任意的,并且由于安全原因,每次运行都会在Python 3中进行更改。 使a.keys()成为lambda的局部变量:

key

答案 1 :(得分:1)

关键在于,您已将lambda函数定义为以下内容:

lambda t: a[key]

您没有使用变量t并尝试通过将变量a作为字典的键来获取key的值。并且在下次您尝试使用此函数时将函数包含在字典理解中:

{key:f(t) for (key,f) in _interpolators.items()}

每次尝试获取f(t)时,由于t的存在是多余的,python尝试通过传递变量{{1}来获取a的值对它来说,它与key无关。

最重要的一点是,您希望python覆盖t变量,因为您在词典理解中使用key

由于key对象是python中的一个函数并且有自己的本地命名空间,因此每次尝试返回lamda时它都无法访问理解中的迭代变量a[key]所以由于LEGB方式(key)在Local命名空间中查找lambda,然后Enclosing并找不到任何内容,它会在全局范围内查找它。

由于全局key是以下部分中的最后一个迭代变量:

key

for key in a.keys(): _interpolators[key] = lambda t: a[key] 函数会将其用作lambda。因为在python 3.X中key的顺序是随机的,结果也是随机的。虽然在python 2中不是这样。

要解决此问题,您只需更改dict.keys(),如下所示:

lambda

在您的代码中:

lambda t: a[t]