我已经深入搜索了这个问题的解决方案,但是,对于Python和tkinter来说,很难找到解决问题的方法,而这些问题主要是您不熟悉的语言。我希望这不是一个重复的问题。
假设我在tkinter中创建了一系列按钮,每个按钮将依次显示字母表中的字母,如下所示:
from string import ascii_uppercase as alphabet
from tkinter import Button
blockLetterButtons = []
for i in range(0,26):
blockLetterButtons.append(Button(competitorSelectionFrame,
text=alphabet[i], command=some_function(alphabet[i])))
for
循环中的某个位置下方的所有内容都是.grid(...)
。
command
属性中引用的函数如下:
def some_function(letter):
print(letter)
所以我认识到我的代码有两个问题:
command
属性中的函数在运行代码时立即执行,因为我指定的是函数调用而不是函数名。alphabet[i]
也不会起作用,因为它会在点击时传递i
的任何值,而不是执行i
循环时for
无论如何。所以我的问题如下:
command
属性中指定函数并使用参数传递给该函数?我相当肯定我可以使用列表解析来解决第二个问题,也许是一个字母,其键等于字母,值等于按钮,但是我仍然不知道如何获得来自按钮的键值。
答案 0 :(得分:0)
Currying是将一些参数传递给函数以生成一个新函数的做法,该函数可以在以后调用,但是会记住"它早先的论点。您可以使用此技术来传递状态。
array
所以def some_function(letter):
def f():
print(letter)
return f
...
command = some_function(alphabet[i])
会调用该函数,但只使用一组括号只是为了以后存储该值。
答案 1 :(得分:0)
您应该使用更高阶函数(返回函数的函数)。为了演示,我不会使用tkinter,但原理是相同的:
In [25]: def some_func_maker(letter):
...: def some_func():
...: print(letter)
...: return some_func
...:
In [26]: buttons = []
In [27]: from string import ascii_uppercase as alphabet
In [28]: for i in range(26):
...: buttons.append(some_func_maker(alphabet[i]))
...:
In [29]: for b in buttons: b()
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
注意,如果您不想使用lambda保持some_func_maker
,则可以内联:
In [37]: buttons = []
...: for c in alphabet:
...: buttons.append(
...: (lambda x: lambda: some_function(x))(c)
...: )
...:
In [38]: for b in buttons: b()
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
一个常见的伎俩是,使用lambda的默认参数并不那么冗长,但是,我认为这更加晦涩,尽管在Python中很常见:
In [43]: buttons = []
...: for c in alphabet:
...: buttons.append(
...: lambda x=c: some_function(x)
...: )
...:
In [44]: buttons[0]()
A
In [45]: buttons[1]()
B
In [46]: buttons[-1]()
Z
另请注意,当您可以简单地迭代迭代时,可以考虑使用for i in range(n): some_iterable[i]
的反模式。通常,您只需要实际值,因此您只需for x in some_iterable
。