我正在使用Tkinter在Python 3.7中创建一个Menu
。当我创建带有硬编码值的菜单时:
obj_menu = Menu(textbox, tearoff=0)
obj_menu.add_command(label="a", command=lambda : foo("a", index))
index = index + 1
obj_menu.add_command(label="b", command=lambda : foo("b", index))
一切正常。在我的回调方法 foo()中,分别选择第一个菜单项和第二个菜单项时,我得到a和b正确的值。
但是当我在for循环中创建此菜单时,我总是在我的回调方法foo()中得到最后一个字符。
for idx, char in enumerate(alphabets):
obj_menu.add_command(label=char, command=lambda : foo(char, idx))
我很困惑,为什么无论我选择哪个菜单索引,该方法都只获取最后一个索引的值。我想念什么吗?
答案 0 :(得分:1)
如果您确实想创建函数列表,而不是使用lambda
,则可以使用functools
库中Python的partial()
函数。例如:
for idx, char in enumerate(alphabets):
obj_menu.add_command(label=char, command=partial(foo, char, idx))
下面在一个小测试示例中显示了两种不同方法的结果:
from functools import partial
def foo(char, idx):
print(char, idx)
return idx
alphabets = "abc"
print("Using lambda")
funcs = []
for idx, char in enumerate(alphabets):
funcs.append([char, lambda : foo(char, idx)])
for char, func in funcs:
print(char, func())
print("\nUsing partial")
funcs = []
for idx, char in enumerate(alphabets):
funcs.append([char, partial(foo, char, idx)])
for char, func in funcs:
print(char, func())
这将显示以下输出:
Using lambda
a 2
a 2
b 2
b 2
c 2
c 2
Using partial
a 0
a 0
b 1
b 1
c 2
c 2
可以看出,第一种方法失败,导致最后一个lambda
变体用于所有调用,而partial()
函数正常工作。
答案 1 :(得分:0)
当您创建该形式的lambda表达式时,实际上您正在执行类似以下操作:
Rebuild Project
我希望您可以看到此index = [whatever value]
def _implicit_func():
return foo("a", index)
obj_menu.add_command(label="a", command=_implicit_func)
变量在函数范围之外也可用。这意味着您可以编辑此变量,它将改变该函数将来的所有执行。
如果您仍然感到困惑,请在Python变量的作用域上使用here's a reference。
答案 2 :(得分:0)
解决方案是在lambda中创建临时变量,并将其用于方法调用中。
for idx, char in enumerate(alphabets):
obj_menu.add_command(label=char, command=lambda c=char, i=idx : foo(c, i))