Python循环调用匿名函数产生的问题

Python循环调用匿名函数产生的问题

问题描述

我有三个字典类型变量和一个接收一个字符串参数的函数,

经过如下操作之后,我希望我的三个字典中每个name对应一个这个函数,

但是这样运行后发现所有的函数接收的path字符串全都是最后一个name对应的path

1
2
3
4
5
6
7
8
9
10
11
# 有三个字典,字典键值对都为字符串类型 name: path,
# 一个函数,接受一个字符串参数

Gui_Dir1, Gui_Dir2, Gui_Dir3 = {},{},{}
def custom(path:str) -> None


for dirs in [Gui_Dir1, Gui_Dir2, Gui_Dir3]:
for name, path in dirs.items():
dirs.update({name: lambda: custom(path)})

期望结果:

1
2
3
4
5
Gui_Dir1 = {name1: path1, name2: path2, name3: path3} # 原本字典变量

==>>
Gui_Dir1 = {name1: func(path1), name2: func(path2), name3: func(path3)}
# 一一对应

实际结果:

1
2
3
4
5
Gui_Dir1 = {name1: path1, name2: path2, name3: path3}  # 原本字典变量

==>>
Gui_Dir1 = {name1: func(path3), name2: func(path3), name3: func(path3)}
# path全为最后一次传参

问题产生原因:

来自GPT3.5的回答

这是因为在循环中,lambda 函数中的 path 是一个变量的引用,而不是一个新的局部变量。所以在每次循环中,lambda 函数都会捕获循环最后一次的 path 值,导致所有的 lambda 函数实际上引用同一个 path 变量。

为了解决这个问题,可以在循环内部创建一个新的作用域,使每个 lambda 函数都引用自己独立的 path 变量。可以通过在循环内部定义一个参数默认值来实现这一点。

修改后代码

1
2
3
4
5
6
7
8
Gui_Dir1, Gui_Dir2, Gui_Dir3 = {},{},{}
def custom(path:str) -> None


for dirs in [Gui_Dir1, Gui_Dir2, Gui_Dir3]:
for name, path in dirs.items():
dirs.update({name: lambda path=path: custom(path)})

出现问题2:

1
2
3
# 传入的参数变成了bool类型变量
path: False
AttributeError: 'bool' object

这个问题小明调试了一段时间也没找到原因,如果有大佬找到原因希望留言给我嗷!万分感谢

最终修改(问题解决):

1
2
3
4
5
6
7
8
9
10
Gui_Dir1, Gui_Dir2, Gui_Dir3 = {},{},{}
def custom(path:str) -> None

def create_func_link(path):
# 通过新声明一个函数,返回所需的匿名函数调用 -->解决
return lambda: custom(path)

for dirs in [Gui_Dir1, Gui_Dir2, Gui_Dir3]:
for name, path in dirs.items():
dirs.update({name: create_func_link(path)})