我编写了一个函数来生成一个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,程序的输出是随机的。它可以是2
或4
,而我希望只有4
。我不太明白这种行为。
请注意,python 2.7.10似乎没有出现“bug”,而且当我多次运行程序时,我总是得到4
。
它是python 3.5.1中的某种错误还是我错过了一些明显的东西?
答案 0 :(得分:1)
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]