I'm learning a little bit of Tkinter in Python, creating interactive windows. The window I'm currently making is one that, given a dict of contacts and their respective contact info, creates a button for each contact which, when pressed, displays their contact info.
The two sample contacts I have are named 'Marvin' and 'Minsky', and their info is stored in a dict named book
:
import Tkinter as tkinter
# 'Phonebook' with contact info for two people.
book = {"Marvin": {"Mobile": "1234567890", "Email": "marvin@gmail.com"},
"Minsky": {"Mobile": "9087865342", "Email": "minsky@yahoo.com"}}
window = tkinter.Tk() # Make window object
def showinfo(name):
# Displays info for person whose button was clicked
# Displays info by configuring labels named 'mobile' and 'email',
# using values in 'book'
mobile.configure(text = book[name]["Mobile"])
email.configure(text = book[name]["Email"])
Here's the important part. Instead of the buttons simply using command = showinfo(name)
to call showinfo()
, as I first tried, a lambda expression is used:
for name in sorted(phonedict.book.keys()):
# Create button for each alphabetically sorted name
btn = tkinter.Button(text = name, command = lambda arg = name: showinfo(arg))
btn.pack()
And the rest of the code is just the labels that showinfo()
modifies:
# Window section where contact info is displayed via labels
mobile_lbl = tkinter.Label(text = "Mobile:")
mobile_lbl.pack()
mobile = tkinter.Label(text = "")
mobile.pack()
email_lbl = tkinter.Label(text = "Email:")
email_lbl.pack()
email = tkinter.Label(text = "")
email.pack()
# Display window
window.mainloop()
When run, this program does exactly what I want it to do, modifying the labels correctly when each button is clicked.
If command = showinfo(name)
is used in place of the lambda, however, NameError: global name 'mobile' is not defined
is thrown because (I think) it tries to execute the button's command when the button is created instead of when it is pressed.
Why would the use of a lambda expression in the button's command keep the command from executing until the button is clicked? What functional purpose is it serving?