Using Lambda Function in Loop Gives Wrong Input Value

I am currently running into an issue using the lambda function and the
partial function in a loop. Code Below:

The problem here is that the lambda's context is not actually
evaluated until after the loop is ended, at which point i has the
value of 1 (or whatever the end value for your loop is). This lazy
evaluation of lambdas by Python is a huge pain for the kind of UI
generation you're doing (and which I use all the time myself). The
solution is to use a default argument value. Compare:

funcs =
for i in xrange(6):

... funcs.append(lambda: i)
...

[f() for f in funcs]

[5, 5, 5, 5, 5, 5]

funcs =
for i in xrange(6):

... funcs.append(lambda i = i: i)
...

[f() for f in funcs]

[0, 1, 2, 3, 4, 5]

-Chris

ยทยทยท

On Wed, Sep 26, 2012 at 8:04 AM, Kayla DesPortes <ksdesportes@gmail.com> wrote:

class CWindow(wx.Frame):
        def __init__(self,parent,id,title):

wx.Frame.__init__(self,parent,-1,title,size=(1000,500),style=wx.DEFAULT_FRAME_STYLE)
                panel = wx.Panel(self)

                cButtons =
                block = 28

                locX = 0
                locY = 0
                for i in range(0,2):
                        currButton = gb.GradientButton(panel,label="C Agent
"+str(i),pos=(locX,locY),size=(block,block))
                        self.Bind(wx.EVT_BUTTON,lambda event, cNum=i:
self.cButtonFunc(event,cNum))
                        # I tried using the partial function below as well
with the same results

#self.Bind(wx.EVT_BUTTON,partial(self.cButtonFunc,cNum=i))

                        currButton.SetDefault()
                        currButton.SetTopStartColour(wx.Colour(51,153,51))
                        currButton.SetTopEndColour(wx.Colour(51,102,51))
                        currButton.SetBottomStartColour(wx.Colour(0,51,0))
                        currButton.SetBottomEndColour(wx.Colour(0,102,0))
                        self.cButtons.append(currButton)
                        locX = 12*block

        def cButtonFunc(self,event,cNum):
                t = wx.MessageDialog(self,"SELECT FOR C AGENT %d WILL GO
HERE!"%cNum, "Select",wx.OK)
                t.ShowModal()
                t.Destroy()

This code is always returning cNum as being 1 because this is the last value
of i. I also tried using the partial function (as commented out in the code
above) to see if it would change anything and it did not. I was searching
online and found that someone used a boxsizer and added the button to the
boxsizer within the loop and this worked for them, but at this point in my
code it would be a huge pain to add box sizer to the GUI for this panel
because i have a lot more buttons than what I am showing here, and they are
mapped out in a design. Does anyone have any suggestions on how to fix this?

Thanks,
~Kayla

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en