Thanks, Cody, that’s exactly what I was looking for. And after I saw
that, I discovered the reason that the non-gui version happened to
work. So the problem was entirely in my understanding of lambda, not
anything to do with wxPython. That extra index argument was coming
from whatever the current value is of the init function’s local
variable i. I was able to show that by adding another assignment to i,
following the loop.
So, now the question is: how can I learn more about lambda? In
working with at least 35 languages over the past 40 years, I’ve never
had such a capability before, and I need to understand its limits. Of
course, lambda is just a special case of the more general notion of
functions as real objects. In every other language I’ve known, a
function had state only while it was executing, and that state was on
the stack. But Python offers at least three ways for functions to have
multiple instances, each containing separate state information:
lambda, callable class objects, and generators.
So far, my working theory is that the only state the function contains
before it begins executing is the default arguments, which are
evaluated when the function is compiled. And the non-argument
externals referenced within the function are resolved into ‘references’
not values, at compile time. In a compiled language without nested
functions, the difference is moot, but here it is significant.
In C++, when I didn’t understand a concept, I’d look at the generated
machine code, and see what was happening. (It didn’t help much when
the compiler didn’t match the language definition, but it usually did.)
And I also knew folks on the C++ ANSI standards comittee. And
eventually I was parading in the depths of the generated intermediate
code from the compiler. But Python still has several concepts that
elude me, and I don’t know where to see the detailed descriptions, nor
do I seem to have tools that let me examine what’s really happening.
My self-assignment for this afternoon: “Programming Python” by Mark
Lutz, 3rd edition, starting with pag 390 (‘Passing in values with
default arguments’, ‘Passing in values with enclosing scope
references’, …) Although I’ve been through it before, maybe this
time it’ll begin making sense.
···
class MouseEventFrame(wx.Frame): def __init__(self, parent, id): wx.Frame.__init__(self, parent, id, title="Testing", size=(300, 120)) self.panel = wx.Panel(self) for i in range(3): self.button = wx.Button(self.panel, label="Button "+str(i), pos=(100, 15 + 20*i )) self.Bind(wx.EVT_BUTTON, lambda evt : self.OnSetRank(evt, i), self.button)
try: self.Bind(wx.EVT_BUTTON, lambda evt, index=i: self.OnSetRank(evt, index), self.button) Cody