0

After alot of research including on on stackoverflow i really can't understand why the code below does not work even after i set the Default value of my variable as alot of people recomended. here is the code

#initial nested array
outter = [["name1",1],["name2",2],["name3",3]]

for inner in outter:
    button = QPushButton()
    button.setText(inner[0])  // create a button with the text
    button.clicked.connect(lambda value=inner[1] : print(value))

The 3 buttons are created each with its respective name ( name1,name2,name3) but when i click them, it prints

False
False 
False

If i change this part of the code, all 3 buttons print the last value "3", as shown below,

 button.clicked.connect(lambda : print(inner[1]))
 3
 3
 3

I already tried doing all sorts crazy things to make this work, any advices?

  • It is a different problem than the one it was linked to, so I reopened the question. The question [linked to](https://stackoverflow.com/q/19837486/296974) operates with a pure lambda, this one uses default parameters. The behaviour should indeed be different. – glglgl Mar 20 '18 at 13:46

1 Answers1

1

I suppose you plainly forgot to press "save" after adding the value=… stuff.

If I replay your problem

outer = [["name1",1],["name2",2],["name3",3]]

# this must have been your original approach and was the same as in the linked question
ll = [lambda: inner[1] for inner in outer]
print(ll[0](), ll[1](), ll[2]()) # gives 3 3 3

# your approach
ll = [lambda value=inner[1]: value for inner in outer]
print(ll[0](), ll[1](), ll[2]()) # gives 1 2 3

# alternative approach
ll = [lambda value=inner: value[1] for inner in outer]
print(ll[0](), ll[1](), ll[2]()) # gives 1 2 3

As was mentioned in the previously linked question, the lambda always accesses the inner variable via its closure, only getting its last and persisting value.

The alternative approaches go the way to link the lambda to the value which is current at creation time and should definitely work. (Note that instead of doung things with buttons, I concentrate on the labda problem.)

Another way could be to have a function which creates "printers" as needed:

def printer(value):
    return lambda: print(value)

With them, you can easily create lambdas which do as you want: print the given value, such as

button.clicked.connect(printer(inner[1]))print(value))
glglgl
  • 89,107
  • 13
  • 149
  • 217
  • Thank you , the best approach i found was your last suggestion, i now have a function that makes lambda functions from mutable values like arrays – Yuri Acesso Mar 20 '18 at 16:53