Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中使用lambda函数dict的奇怪行为_Python_Python 3.x_Lambda - Fatal编程技术网

python中使用lambda函数dict的奇怪行为

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()中最后一个元素的值。由于安全原因,

我编写了一个函数,用于生成lambda常量函数的词汇表(它是更复杂函数的一部分,但我已将其简化为以下代码):

在OSX El Capitan上使用Python 3.5.1,程序的输出是随机的。它可以是
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"])