在for循环中创建Menu使用Python中的最后一个索引值

时间:2019-07-15 06:12:25

标签: python python-3.x tkinter

我正在使用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))

我很困惑,为什么无论我选择哪个菜单索引,该方法都只获取最后一个索引的值。我想念什么吗?

3 个答案:

答案 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))

感谢您的回答:https://stackoverflow.com/a/17677768/970422