python:dict of(lambda)函数

python:dict of(lambda)函数,python,lambda,Python,Lambda,在将lambda函数存储到字典中时,我经历了一些奇怪的行为:如果您尝试将一些默认值传递给循环中的函数,则只使用最后一个默认值 下面是一些最简单的例子: #!/usr/bin/env python # coding: utf-8 def myfct(one_value, another_value): "do something with two int values" return one_value + another_value fct_dict = {'add_{}'.

在将lambda函数存储到字典中时,我经历了一些奇怪的行为:如果您尝试将一些默认值传递给循环中的函数,则只使用最后一个默认值

下面是一些最简单的例子:

#!/usr/bin/env python
# coding: utf-8

def myfct(one_value, another_value):
    "do something with two int values"
    return one_value + another_value

fct_dict = {'add_{}'.format(number): (lambda x: myfct(x, number))
            for number in range(10)}

print('add_3(1): {}, id={}'.format(fct_dict['add_3'](1), id(fct_dict['add_3'])))
print('add_5(1): {}, id={}'.format(fct_dict['add_5'](1), id(fct_dict['add_5'])))
print('add_9(1): {}, id={}'.format(fct_dict['add_9'](1), id(fct_dict['add_9'])))
输出内容如下

add_3(1): 10, id=140421083875280
add_5(1): 10, id=140421083875520
add_9(1): 10, id=140421083876000
可以得到不同的函数(id不相同),但每个函数都使用相同的第二个参数

有人能解释一下发生了什么事吗

python2、python3、pypypy…的修复程序也是如此:

def make_closure(number):
    return lambda x: myfct(x, number)
用作

{'add_{}'.format(number): make_closure(number) for number in range(10)}
这种行为的原因是,变量
number
(思考:此处命名的内存位置)在循环的所有迭代中都是相同的(尽管其实际值在每次迭代中都会发生变化)。这里的“循环”是指字典理解,它在内部是基于循环的。在循环中创建的所有
lambda
实例将在相同的“位置”上关闭,该位置保留上次分配给它的值(在循环的最后一次迭代中)

下面的代码不是下面实际发生的代码。本文件仅用于阐明以下概念:

# Think of a closure variable (like number) as being an instance
# of the following class

class Cell:
    def __init__(self, init=None):
        self.value = None

# Pretend, the compiler "desugars" the dictionary comprehension into
# something like this:

hidden_result_dict = {}
hidden_cell_number = Cell()

for number in range(10):
    hidden_cell_number.value = number
    hidden_result_dictionary['add_{}'.format(number)] = create_lambda_closure(hidden_cell_number)
create\u lambda\u closure
操作创建的所有
lambda
闭包共享非常相同的
Cell
实例,并将在运行时(即实际调用闭包时)获取
value
属性。到那时,
value
将引用分配给它的最后一个值


然后,
hidden\u result\u dict
的值作为dict理解的结果被回答。(同样:这只是在“概念”层面上阅读;它与Python VM执行的实际代码无关)。

number
是一个变量,对于dict理解的每次迭代都有不同的值。但是当您执行
lambda x:myfct(x,number)
时,它不使用
number的值。它只是创建一个lambda方法,在调用/使用它时使用number的值。因此,当您使用
add{}
方法时,
number
具有值
9
,该值在对
myfct(x,number)的每次调用中使用

你是想在词汇声明中使用“列表理解”吗?正确:如果我需要不同的名称,我有时会使用它来创建一组条目/函数->请参阅以获得词汇理解我发现你的答案比这个问题的答案好得多这是一个重复的问题。你可能也想在那里添加你的答案,让更多的人看到它。非常感谢,我因为这个错误而发疯,浪费了3个小时试图了解发生了什么