I’m having issues using lambda functions to dynamically create commands for my Tkinter GUI, and the suggested solutions I’ve found on SO don’t seem to work as expected.
The objective of this simple code is to create a GUI that should have two buttons, one that says “Buy Apple” and one that says “Buy Banana”. When the user clicks the ‘apple’ button, it should print a message that says ‘You bought 1 apple’ and when they click the ‘banana’ button, it should print a message that says ‘You bought 1 banana’.
The original form was this:
import tkinter as tk
from functools import partial
root = tk.Tk()
def print_buy(fruit):
print('You bought 1 ' + f)
for f in ['Apple', 'Banana']:
btn = tk.Button(
root,
text = 'Buy ' + f,
command = lambda: print_buy(f)
)
btn.pack()
root.mainloop()
Now, I understand this doesn’t work because the command will reference the CURRENT value of f when the button is clicked, which will be ‘banana’, since that’s the value at the end of the loop. There are two suggested solutions on Stack Overflow here. The problem is, neither one is working as expected.
Suggested Fix 1: Partials
One suggestion is to use partials to ‘freeze’ the value in place. Here’s the loop with the partials:
for f in ['Apple', 'Banana']:
btn = tk.Button(
root,
text = 'Buy ' + f,
command = partial(print_buy, f)
)
btn.pack()
Nope. Still get ‘You get 1 banana’ for both buttons.
Suggested Fix 2: Assignment
OK, trying the other method suggested–assigning a variable inside the lambda function.
for f in ['Apple', 'Banana']:
btn = tk.Button(
root,
text = 'Buy ' + f,
command = lambda f=f: print_buy(f)
)
btn.pack()
Nothing but bananas.
Experimental Fix: Variable Variation
OK, maybe reusing the btn
variable is causing issues?
for f in ['Apple', 'Banana']:
btn_var = 'btn_' + f.lower()
locals()[btn_var] = tk.Button(
root,
text = 'Buy ' + f,
command = lambda f=f: print_buy(f)
)
locals()[btn_var].pack()
Nope, more bananas.
I’m sure I’ve missed something very basic here but I’ve been troubleshooting this for an hour and for the life of me I can’t work out what the problem is.