"Thanks" * INFINITY hum weirdly it worked ... not yet understood why!
Here is a post on it: https://www.linkedin.com/feed/update/urn:li:activity:6554081428492161024/ Thanks for all! On Mon, Jul 8, 2019 at 5:40 PM Calvin Spealman <cspea...@redhat.com> wrote: > This is a really common scoping issue to get tripped up on. I'll try to > help you understand and work around it. > > for i, icon in enumerate(self.icons): > print('// entering', icon.program) > print('icons ... ... ... ...') > pretty(icon.info, icon.program) > x = Button(root, text=icon.info['name'] +'\n' + icon.info['version'], > image=icon.photo, > compound=LEFT, > command=lambda: self.button_exec(icon)) > > On the first line you enter a for loop where each iteration assigns a > different pair of values to the names "i" and "icon". > On the last line you create a lambda, an anonymous function, which you > pass as the command callback for the button. Of course, no code inside the > lambda is actually executed at this point. It is only after the entire for > loop has completed, later when the user sees the buttons and clicks on one > of them, that one of the lambda callbacks for the appropriate button will > be executed. > Now, when this happens, what is the value of "icon"? This involves a > closure, which is how we describe the effect of the lambda (or any > function) being created inside the scope of another function. The scope > here which contains the "icon" variable is kept after the for loop and its > container function is complete, because the lambda you create holds on to > it in order to resolve variable names from. So all the lambda functions > read the "icon" variable from this same scope, and at the time the loop > completes that variable is assigned to the LAST value from the loop. That's > why all the buttons get the same icon. > There is a simple work around, however, called "rebinding". It is a trick > you can do with default values for lambda or any function. Simply pass the > icon as a default value for a parameter to the lambda, and the value at > that time for one iteration of the loop will be bound to the callback you > create. > > Just change this > > lambda: self.button_exec(icon) > > to this > > lambda icon=icon: self.button_exec(icon) > > I hope both the explanation and the example help! > > > On Mon, Jul 8, 2019 at 1:59 AM Abdur-Rahmaan Janhangeer < > arj.pyt...@gmail.com> wrote: > >> Greetings, >> >> I'm doing this project: >> >> >> https://github.com/Abdur-rahmaanJ/cmdlaunch/blob/master/cmdlaunch/cmdlaunch.py >> >> Everything works fine, except for one thing. >> >> On line 60, the button is taking an object in it's command parameter >> >> If you run the file, you'll see that all the different names are written >> on >> the gui just the callback is takest the newest icon object for all three >> buttons >> >> I know just a reference issue but it's been **bugging** me. >> >> Thanks All >> >> -- >> Abdur-Rahmaan Janhangeer >> Mauritius >> -- >> https://mail.python.org/mailman/listinfo/python-list >> > > > -- > > CALVIN SPEALMAN > > SENIOR QUALITY ENGINEER > > cspea...@redhat.com M: +1.336.210.5107 > [image: https://red.ht/sig] <https://red.ht/sig> > TRIED. TESTED. TRUSTED. <https://redhat.com/trusted> > -- Abdur-Rahmaan Janhangeer http://www.pythonmembers.club | https://github.com/Abdur-rahmaanJ Mauritius -- https://mail.python.org/mailman/listinfo/python-list