Python 如何从循环中创建的对象向函数传递特定于对象的值?
我已经深入地寻找了这个问题的解决方案,但是,由于对Python和tkinter不熟悉,很难用您基本不熟悉的语言找到问题的解决方案。我希望这不是一个重复的问题 假设我在tkinter中创建了一系列按钮,每个按钮将依次显示字母表中的一个字母,定义如下:Python 如何从循环中创建的对象向函数传递特定于对象的值?,python,function,for-loop,tkinter,Python,Function,For Loop,Tkinter,我已经深入地寻找了这个问题的解决方案,但是,由于对Python和tkinter不熟悉,很难用您基本不熟悉的语言找到问题的解决方案。我希望这不是一个重复的问题 假设我在tkinter中创建了一系列按钮,每个按钮将依次显示字母表中的一个字母,定义如下: from string import ascii_uppercase as alphabet from tkinter import Button blockLetterButtons = [] for i in range(0,26): b
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
循环的下面的某个地方有一个网格(…)
命令
属性中引用的函数如下所示:
def some_function(letter):
print(letter)
因此,我认识到我的代码存在两个问题:
命令
属性中的函数在运行代码时立即执行,因为我指定的是函数调用而不是函数名
即使这是使用参数调用函数的正确方法,使用字母[i]
也不会起作用,因为它会在单击时传递i
的值,而不是执行for
循环时传递的i
因此,我的问题如下:
def some_function(letter):
print(letter)
如何在命令
属性中指定函数,并将参数传递给该函数
如何将该参数指定为特定于该按钮的字母表中的字母,而不为每个字母明确定义按钮
我很确定我可以用列表理解来解决第二个问题,也许是一本键等于字母,值等于按钮的字典,但是,我仍然不知道如何从按钮本身获取键值。是一种将一些参数传递给函数以生成新函数的实践,该函数可以在以后调用,但“记住”其早期参数。您可以使用此技术来传递状态
def some_function(letter):
def f():
print(letter)
return f
...
command = some_function(alphabet[i])
因此,一些函数(字母表[i])()
会调用该函数,但仅使用一组括号就可以存储值供以后使用。您应该使用高阶函数(返回函数的函数)。为了演示,我将不使用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在周围保留某个函数生成器
,则可以将其内联:
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
注意,在“范围”(n)中,使用“<代码>”为“反模式”:当您可以简单地迭代迭代时,可以使用一些可迭代的[i] < /代码>。通常,您只需要实际值,因此您只需在某个_iterable
command=lambda i=i:some_函数(字母表[i])中对x执行。
是惯用的解决方案。lambda生成一个函数,以后可以调用该函数,而不需要任何参数;带有默认值的参数i
在定义lambda时捕获外部i
的值,因此每个按钮都有其独特的值。这当然是惯用的方法,比我的答案更简洁。我可以建议你自己把这个作为答案吗?@jasonharper这个解决方案非常有效,谢谢。因此lambda为每个按钮生成一个函数,并为循环中的当前实例i生成一个函数。我到底做什么?这是lambda创建的函数的参数吗command=partial(print,alphabet[i])
在不定义新的currying实用程序函数的情况下可以工作。严格来说,这不是currying,而是部分应用程序,但我经常混淆这两个功能。。。