0

This issues is related to pyside(6). The following code should work, but I keep getting a single value 't' as the result when a button is clicked.

labels_list = ["y", "t", "u", "N", "T", "U"]
who_cb_list = []
for ii in range(6):
    who_cb_list.append(qtw.QRadioButton())
    who_cb_list[ii].setText(labels_list[ii])
    who_cb_list[ii].clicked.connect(lambda ii=ii: self.setWho(labels_list[ii]))

Originally I made the mistake of

    who_cb_list[ii].clicked.connect(lambda: self.setWho(labels_list[ii]))

When I clicked on the radio button of course I always connect the last value of the list ('U') on every button.

But the new way (lambda ii=ii:) still caused an error. Oddly I would always get 't'. I asked chatGPT and got this suggestion which worked.

def create_lambda_handler(label):
    return lambda: self.setWho(label)

for ii, label in enumerate(labels_list):
    who_cb_list.append(qtw.QRadioButton())
    who_cb_list[ii].setText(label)             
    who_cb_list[ii].clicked.connect(create_lambda_handler(label))

The function defined outside the loop makes a closure.... Another way to do this turned out to be using func tools:

import functools

for ii, label in enumerate(labels_list):
   who_cb_list.append(qtw.QRadioButton())
   who_cb_list[ii].setText(label)             
   who_cb_list[ii].clicked.connect(functools.partial(self.setWho, label))

From chatGPT: functools.partial is a function in the Python standard library that allows you to create partial function application. It's a way to "freeze" some portion of a function's arguments, creating a new function with those arguments pre-filled.

user2390182 provided this link which explains all this: Common Gotchas — The Hitchhiker's Guide to Python

Here is the entire exchange with chatGPT https://chat.openai.com/share/afa29ada-e97d-476c-b67d-495f657d5278

2
  • I'm not sure if by "get the current value into the lambda expression" you mean executing the anonymous function with current value (ii I suppose?) as its input parameter or something else. See my answer and please elaborate. Commented Jul 8, 2023 at 6:15
  • docs.python-guide.org/writing/gotchas/#late-binding-closures Commented Jul 8, 2023 at 7:42

1 Answer 1

0

I'll post an answer, as this is a bit much for the comment section. I can't quite figure out what you're trying to do and what the lambda is supposed to do. I'll edit/delete later.

Is it on purpose to use both who_cb_list and self.who_cb_list ? It seems you only define the lambda (and thereby return the anonymous function itself) but never execute it (unless that's happening within connect)

For instance here I provide (i) as the input to lambda so that I get a value in return and not the function:

for i in range(6):
    a = (lambda x:x+1)(i)
    print(i,a)
0 1
1 2
2 3
...
Sign up to request clarification or add additional context in comments.

2 Comments

Apologies, I have updated my question. The connect is assigning what will happen when.a radio button is pressed. When that button is pressed, it always gets the last argument in the labels_list because that is the last valid value for ii. I want to capture what the value for ii is at the time I connect the callback to the radiobutton.
Understood. It happens because you return only a function (the lambda function) if you don't provide the input parameter to the lambda. You don't need ii inside the lambda, any placeholder var will do. You need to provide ii as the parameter (in my example x is the placeholder and with (i) I provide the actual value). Try if that works.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.