python中使用lambda函数dict的奇怪行为
我编写了一个函数,用于生成lambda常量函数的词汇表(它是更复杂函数的一部分,但我已将其简化为以下代码): 在OSX El Capitan上使用Python 3.5.1,程序的输出是随机的。它可以是python中使用lambda函数dict的奇怪行为,python,python-3.x,lambda,Python,Python 3.x,Lambda,我编写了一个函数,用于生成lambda常量函数的词汇表(它是更复杂函数的一部分,但我已将其简化为以下代码): 在OSX El Capitan上使用Python 3.5.1,程序的输出是随机的。它可以是2或4,而我希望只有4。我不太明白这种行为 请注意,Python2.7.10似乎没有出现“bug”,当我多次运行程序时,我总是得到4 这是Python3.5.1中的某种错误,还是我遗漏了一些明显的错误?lambda中的key取自函数的范围。因此它具有a.keys()中最后一个元素的值。由于安全原因,
2
或4
,而我希望只有4
。我不太明白这种行为
请注意,Python2.7.10似乎没有出现“bug”,当我多次运行程序时,我总是得到4
这是Python3.5.1中的某种错误,还是我遗漏了一些明显的错误?
lambda中的key
取自函数的范围。因此它具有a.keys()
中最后一个元素的值。由于安全原因,字典中键的顺序是任意的,每次运行都会在Python 3中更改。
使键
成为lambda的局部变量:
def function(a):
_interpolators = {key: (lambda t, k=key: a[k]) for key in a}
def _interpolate(t):
return {key:f(t) for (key,f) in _interpolators.items()}
return _interpolate
关键是在lambda
函数中,您将其定义为:
lambda t: a[key]
您没有使用变量t
,而是试图通过将变量键作为字典键传递来获取a
的值。在下一次尝试在词典理解中使用此函数时,请将函数包含在词典理解中:
{key:f(t) for (key,f) in _interpolators.items()}
每次您试图获取f(t)
,因为t
的存在在这里是多余的,python试图通过向其传递变量key
来获取a
的值,而这与t
无关
最重要的一点是,您希望python重写key
变量,因为您在字典理解中使用key
由于lamda
对象是python中的一个函数,并且有自己的本地名称空间,因此每次它试图返回a[key]
时,它都无法访问理解内部的迭代变量key
,因此由于后面的LEGB方式(lambda
)在本地命名空间中查找键
,然后将其封闭起来,但什么也找不到,它在全局范围中查找它
由于全局键
是以下部分中的最后一个迭代变量:
for key in a.keys():
_interpolators[key] = lambda t: a[key]
lambda
功能将其用作键
。因为在Python3.X中,dict.keys()
的顺序是随机的,所以结果也是随机的。而在Python2中情况并非如此
为了解决这个问题,您只需更改lambda
,如下所示:
lambda t: a[t]
在您的代码中:
def function(a):
_interpolators = {}
for key in a.keys():
_interpolators[key] = lambda t: a[t]
def _interpolate():
return {k:f(k) for k,f in _interpolators.items()}
return _interpolate
if __name__ == '__main__':
d = {"foo": 2, "bar":4}
f = function(d)
print(f()["bar"])
@尼古拉斯·鲁吉尔:FWIW,你可以在@Kasramvd上阅读更多关于散列随机化的内容:丹尼尔在他的前两句话中解释了OP代码的主要问题。然而,由于随机的PYTHONHASHSEED
问题,OP的错误代码的结果因运行而异。@PM2Ring实际上,如果我说得更好,这并不能解释主要问题,项目顺序是最后也是最小的问题。这都是关于函数名称空间的。@NicolasRougier欢迎,所以你可以通过接受答案告诉社区。你的函数做了一些其他的事情,而不是OP的意图。你的\u插值器
字典没有任何意义。看看我的解决方案,看看如何正确地执行。@Daniel这不是OP的意图,这只是OP试图解释主要问题的一个例子,我在回答中所说的是OP面临的问题的完整描述,最后一个建议就是跨越这个目标。@Daniel实际上,我不关心我通过投票和接受而获得的这个假想分数,问题是最完整的答案应该被OP接受。这是因为未来的读者更关心被接受的答案。@Kasramvd:OP有一些功能f[key](t)
。这显然不是f(k)
。一个解释可能是尽可能好的,如果它不能解决问题,它是毫无价值的。OP的lambdas中的t
在他的简单示例中可能没有使用,但在他的实际问题中没有。
def function(a):
_interpolators = {}
for key in a.keys():
_interpolators[key] = lambda t: a[t]
def _interpolate():
return {k:f(k) for k,f in _interpolators.items()}
return _interpolate
if __name__ == '__main__':
d = {"foo": 2, "bar":4}
f = function(d)
print(f()["bar"])