Take the 2-minute tour ×

I'm trying to build a little num pad using tkinter, to be able to enter a password code on a pure touchsystem. This is what I have so far:

import tkinter from tkinter import ttk

def main():
    root = tkinter.Tk()
    numpad = NumPad(root)

btn_list = [
'7',  '8',  '9',
'4',  '5',  '6',
'1',  '2',  '3', '0']

class NumPad(ttk.Frame):
    def __init__(self, root):
        ttk.Frame.__init__(self, root)

    def numpad_create(self):
        r = 1
        c = 0
        for b in btn_list:
            cmd= lambda: print(b)
            self.b= ttk.Button(self, text=b,width=5,command=cmd).grid(row=r,column=c)
            c += 1
            if c > 4:
                c = 0
                r += 1


If I start the programm, it prints the numbers b to the shell, so this works. Also the Buttons are displayed as wished. But if I click them, I get always 0 as output to the shell. I can't find the mistake I've done, I think it might has something to do with garbage-collecting, but I am not sure though.

Could somebody help me? It would be really great!

Thank you!

share|improve this question
add comment

3 Answers

up vote 2 down vote accepted

cmd, your lambda, does not catch the value of b when the lambda itself was declared. the final state of b is 0, and that is why all your buttons end up printing b.

share|improve this answer
Thank you, works perfectly!! –  user2304540 Apr 29 '13 at 19:33
add comment

Your lambda should be specified like this:

cmd= lambda b=b: print(b)

This will bind the current value of b to be the default value of the parameter named b in your lambda. Without this binding, the lambda will use the value of b at the time it is pressed rather than the value at the time it was created.

Personally I find it confusing to use the same variable in both contexts; I personally would write it like this, which is functionally identical but a little easier to understand:

cmd= lambda button=b: print(button)
share|improve this answer
Thank you, that solves the problem! –  user2304540 Apr 29 '13 at 19:33
add comment

The for loop in NumPad.numpad_create loops over each of the button numbers and stores them in self.b. The problem is that each number overwrites the previous value of self.b, so that the only value that is actually stored is 0. tkinter automatically garbage collects objects that do not have a live reference. Add another attribute to NumPad which is a list and put all of your button objects into it.

@thkang is also right: I think that there are two separate bugs. Note that I haven't actually tested this.

share|improve this answer
add comment

Your Answer


