The following is the simplest code required to illustrate my question:
def function_one():
pass
def function_two():
pass
def button_clicked(function_name_as_string):
# do stuff common to all button clicks
# here...
# then respond to specific button click by converting the
# supplied function name string into an actual function which runs.
eval(function_name_as_string "()")
button_one = Button(root,text="Run Function One",
command=lambda: button_clicked("function_one"))
button_two = Button(root,text="Run Function Two",
command=lambda: button_clicked("function_two"))
This is an attempt to make my tkinter code as compact as possible. Here, there are multiple buttons. But rather than write a function to handle each button click, I wanted a single function to handle all button clicks. In particular, that's because there are some operations I want to execute in response to any button click, before responding to the specific button click. At the same time, I wanted to eliminate any lengthy if/elif statement in the button_clicked
function, which would be required for the function to know which button had been clicked, and take appropriate action.
In my solution above, when a button is clicked, the command
keyword calls my button_clicked
function, but also uses lambda
to send the name of the function I want to run in response to the button click. The button_clicked
function executes the code common to all button clicks, then uses eval
to convert the supplied function name (passed as a string) into an actual function that now runs.
So the button_clicked
function is not aware of which button was clicked. Rather, it is aware of what function ought to run in response to the specific button click. And this code runs perfectly.
I have never used lambda before, nor have I used eval. I came across both during a long search. But because both are new to me, I am a bit wary. My question is simply this: is the above approach correct and sound? Or are there hidden pitfalls that I may not be aware of? Thanks in advance.
CodePudding user response:
I would argue it's better to pass the actual function than the function name as a string. eval
rarely adds any value over other solutions, and mostly just makes the code harder to understand.
def function_one():
pass
def function_two():
pass
def button_clicked(function):
# do stuff common to all button clicks
# here...
# then respond to specific button click by calling
# the specified function
function()
button_one = Button(root,text="Run Function One",
command=lambda: button_clicked(function_one))
button_two = Button(root,text="Run Function Two",
command=lambda: button_clicked(function_two))