Tkinter lambda 函数[重复]
- 2025-03-04 08:25:00
- admin 原创
- 111
问题描述:
(正如‘家庭作业’标签所示,这是计算机科学一个大项目的一部分。)
我正在用 tkinter 在 Python 中编写Jeopardy!模拟,在按钮中使用 lambda 函数时遇到了一个大问题。假设root = Tk()
和categories
是一个列表。
# Variable to keep the buttons
root._buttons = {}
# Display headers on top of page
for i in range(5):
# Get category name for display in main window
name = categories[i]
b = Label(root, text=fill(name.upper(), 10), width=18, height=3,\n bg="darkblue", fg="white", font=("Helvetica bold", "", 11))
b.grid(row=0, column=i)
# Create list of buttons in that variable (root._buttons)
btnlist = [None]*5
# Display individual questions
for j in range(5):
# Make a button for the question
b = Button(root, text="$" + str(200 * (j+1)), width=8, height=1,
bg="darkblue", fg="orange", font=("Impact", "", 30))
b.cat = name
b.value = 200 * (j + 1)
b.sel = lambda: select(b.cat, b.value)
# Add callback event to button
print(b.cat, b.value, b.sel)
b.config(command=b.sel)
# Add button to window
b.grid(row=j+1, column=i)
# Append to list
btnlist[j] = b
root._buttons[categories[i]] = btnlist
对于所有代码,请参阅我的小型代码查看器(正在建设中!)
问题似乎就出在这里lambda: select(b.cat, b.value)
,因为当我点击板上的任何按钮时,它总是转到板上的最后一个按钮。我尝试过其他方法,不幸的是,所有方法都使用了lambda
,而且我还没有看到任何不涉及 的方法lambda
。
解决方案 1:
改变
lambda: select(b.cat, b.value)
到
lambda b = b: select(b.cat, b.value)
在您的原始代码中,b
不是的局部变量lambda
;它位于封闭范围内。一旦for-loop
完成,b
它保留最后一个值。这就是为什么lambda
所有函数都使用最后一个按钮的原因。
如果将 lambda 定义为采用一个具有默认值的参数,则默认值在定义lambda 时确定(并固定)。 Nowb
是的局部变量lambda
,当不带参数调用 lambda 时,Python 会将其设置b
为默认值,该默认值可根据需要设置为各种不同的按钮。
解决方案 2:
如果您用函数工厂替换 lambda 表达式,它将使您更具表现力。(假设您将多次调用它)。这样,您以后就可以进行分配、添加更复杂的逻辑等,而不必处理 lambda 的限制。
例如:
def button_factory(b):
def bsel():
""" button associated with question"""
return select(b.cat, b.value)
return bsel
给定一个输入b
,button_factory
返回一个可调用的函数,()
该函数将返回您想要的内容。唯一的区别是您可以进行赋值等。
尽管它最初可能会占用更多的代码行,但它以后会给你更大的灵活性。(例如,你可以将计数器附加到 bsel 并能够计算出某个特定问题被选择了多少次,等等)。
它还有助于自省,因为你可以让每个文档字符串清楚地标识它与哪个问题相关,等等。
扫码咨询,免费领取项目管理大礼包!