[New-bugs-announce] [issue8283] series of lamdas in loop sets the paramater on all calls to that of the last call

alan hoover report at bugs.python.org
Thu Apr 1 20:26:02 CEST 2010

New submission from alan hoover <alan.hoover at gmail.com>:

building a screen using Tkinter based on information from a database to let user take action on the database rows.  I don't know how many rows there will be, so I'm storing the widgets in arrays for each column.

for row in getDBrows():
    self.buttons.append(Tkinter.Button(self,text='UnLoad it', command=lambda :self.unload(row[0])))

When executing the above code, all the buttons have the key to the database table that belongs to the last row.  I found a work around -- by moving the call to create the button (containing the lambda) to a separate function and call that function to create the button instead of creating the button directly, the buttons then make their callback with a correct database key.

for row in getDBrows():
def buildbutton(self,key):
    return Tkinter.Button(self,text='UnLoad it', command=lambda: self.unload(key))

When using the workaround code instead of the original code, the button
for each row has the appropriate key to the database.

It acts like the lambda definitions don't get solidified until the containing block exits; at that time, the lambda definition(s) get locked in with the current value of the variable getting passed into the lambda as a parameter.  By moving the lambda call to a different block (separate function), the lambda gets "locked" when that block (function) exits instead of when the containing block (loop) exits.

components: IDLE, Tkinter, Windows
messages: 102120
nosy: alan.hoover
severity: normal
status: open
title: series of lamdas in loop sets the paramater on all calls to that of the last call
type: behavior
versions: Python 2.6

Python tracker <report at bugs.python.org>

More information about the New-bugs-announce mailing list