3

I am trying to make a number of checkboxes based on a list, however it looks as if I am screwing up the command call and variable aspect of the button.

My code is:

class Example(Frame):

def __init__(self, parent):
    Frame.__init__(self, parent)

    self.parent = parent
    self.initUI()

def initUI(self):

    self.courses = ["CSE 4444", "CSE 4343"]
    self.vars = []

    self.parent.title("Homework Helper")

    self.course_buttons()

    self.pack(fill=BOTH, expand=1)

def course_buttons(self):
    x = 0
    y = 0

    for i in range(0, len(self.courses)):
        self.vars.append(IntVar())
        cb = Checkbutton(self, text=self.courses[i],
                         variable=self.vars[i],
                         command=lambda: self.onClick(i))
        cb.select()
        cb.grid(column=x, row=y)
        y = y+1

def onClick(self, place):

    print place
    if self.vars[place].get() == 1:
        print self.courses[place]

The test so far is for the course to be printed on the console when the check box is on, however it only works for the second button, button "CSE 4343". When I interact with button "CSE 4444", nothing is printed.

Also, the "place" value is onClick is always 1, whether I am clicking button "CSE 4343" or button "CSE 4444".

3
  • What exactly is not working? What's the expected behavior compared to the observed behavior? Any error messages? Commented Apr 24, 2015 at 1:44
  • @TigerhawkT3 I addressed those in my edit sorry. Commented Apr 24, 2015 at 1:50
  • 1
    Due to lambda closure scoping, try lambda i=i: self.onClick(i). Commented Apr 24, 2015 at 2:15

1 Answer 1

7

When you make a lambda function, its references only resolve into values when the function is called. So, if you create lambda functions in a loop with a mutating value (i in your code), each function gets the same i - the last one that was available.

However, when you define a function with a default parameter, that reference is resolved as soon as the function is defined. By adding such a parameter to your lambda functions, you can ensure that they get the value you intended them to.

lambda i=i: self.onClick(i)

This is referred to as lexical scoping or closure, if you'd like to do more research.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.