I’ve written a simple calculator code in Python using Tkinter. Almost every function works but I can’t seem to figure out what the lambda function does in my project. If I add it works without any bug but if I remove it shows an error.
Here is the block where the error points out
class Calc: def __init__(self): self.total = 0 self.current = '' self.ip_val = True self.check_sum = False self.op = '' self.result = False def operation(self, op): self.current = float(self.current) #this line generates error if self.check_sum: self.valid_function() elif not self.result: self.total = self.current self.ip_val = True self.check_sum = True self.op = op self.result = False
Here’s the line calling the CALC class’s operation method.
Button(calc, text='x^y', width=6, height=2, font=('arial', 20, 'bold'), bd=4, bg="gray20", command= res.operation('pow')).grid(row=1, column=5, pady=1)
Traceback (most recent call last): File "T:/WorkSpace/PythonCourse/Day-6.py", line 235, in <module> command= res.operation('pow')).grid(row=1, column=5, pady=1) File "T:/WorkSpace/PythonCourse/Day-6.py", line 69, in operation self.current = float(self.current) ValueError: could not convert string to float: ''
FYI, I know IF I initialize the Button class like below ( with lambda function )
Button(calc, text='x^y', width=6, height=2, font=('arial', 20, 'bold'), bd=4, bg="gray20", command= lambda: res.operation('pow')).grid(row=1, column=5, pady=1)
IT WORKS JUST FINE.
I want an explanation of how this lambda function is the solution to this error. And also if the user doesn’t press the button, the function shouldn’t call itself. How’s this even compiling?
Consider this line of code:
Button(..., command= res.operation('pow'))
It will behave exactly the same as these two lines of code:
result = res.operation('pow') Button(..., command= result)
This is simply how python works. It’s not unique to tkinter. When python sees
x(y), it executes
x immediately under most circumstances.
See the problem?
res.operation('pop') immediately calls the function when you create the button, not when you click the button. When defining a button, you need to set the
command attribute to a callable.
There are several ways to tell tkinter what function to call. If you didn’t have any arguments you would just give it the name of the function itself:
However, in this case, you need to pass an argument so you can’t just pass the function name to the command. You need to pass both the name and the argument. This is where
lambda comes in.
lambda creates a new function, and passes that function to the
Button(..., ,command=lambda res.opeeration('pow')) is roughly the same as this:
def i_dont_care_what_the_name_is(): res.operation('pow') Button(..., command=i_dont_care_what_the_name_is)
Note, it’s not exactly the same, but the differences are unimportant in this discussion.
Bottom line is that
lambda gives an easy way to pass a callable to a function or to assign it to an attribute or variable.
For the record, another way to get the same result is to use functools.partial. Some people prefer that over
lambda, though using
lambda doesn’t require an extra import the way