Tkinter lambda function Tkinter lambda function tkinter tkinter

Tkinter lambda function


Change

lambda: select(b.cat, b.value)

to

lambda b = b: select(b.cat, b.value)

In your original code, b is not a local variable of the lambda; it is found in enclosing scope. Once the for-loop is completed, b retains it last value. That is why the lambda functions all use the last button.

If you define the lambda to take one argument with a default value, the default value is determined (and fixed) at the time the lambda is defined. Now b is a local variable of the lambda, and when the lambda is called with no arguments, Python sets b to the default value which happily is set to various different buttons as desired.


It would let you be more expressive if you replaced the lambda expression with a function factory. (presuming that you're going to call this multiple times). That way you can do assignments, add more complicated logic, etc later on without having to deal with the limitations of lambda.

For example:

def button_factory(b):    def bsel():        """ button associated with question"""        return select(b.cat, b.value)    return bsel

Given an input b, button_factory returns a function callable with () that returns exactly what you want. The only difference is that you can do assignments, etc.

Even though it may take up more lines of code initially, it gives you greater flexibility later on. (for example, you could attach a counter to bsel and be able to count how many times a particular question was selected, etc).

It also aids introspection, as you could make each docstring clearly identify which question it is associated with, etc.