Can’t figure out what lambda function does in my tkinter project

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)

ERROR MESSAGE

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.

QUERY

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?

Answer

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:

Button(..., command=res.operation)

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 command parameter.

In effect, 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 functools.partial does.